diff --git a/docs/adrs/0009-guildhall-practice-model.md b/docs/adrs/0009-guildhall-practice-model.md index 7c0191e..d67a9ec 100644 --- a/docs/adrs/0009-guildhall-practice-model.md +++ b/docs/adrs/0009-guildhall-practice-model.md @@ -18,7 +18,7 @@ Spotify's premium **Skill Exchange** (skills on user profiles, opportunity marke Chosen: the split hub model, named the **Guildhall** (norse kenning skin *Gildaskáli*; "practice layer" was rejected for its verb reading). Concepts: **Skill** (unowned shared vocabulary on people, have/learning axis) · **Craft** (demand-side skill bundle a muster calls for) · **Gildi** (the fellowship — purely people, craft- or aspect-aligned) · **Aspect** (the cross-cutting concern, AOP sense — it **holds the Standards** and ships both the bar and the paved road to clear it) · **Standard → Trials** (tiered checks; every trial declares a remediation **vísir**) · **Vísir** (procedure doc; teaching grade in `/docs`, operational parameterized grade in `/runbooks`). The split that carries the model: *crafts are what people do; aspects are what things must uphold.* -Mapping introduces **no new custom kinds**: gildi = `Group` with `spec.type: gildi`; skills/crafts/aspects = vocabularies; standards = Git-backed YAML for the future scorecard plugin (Tech Insights evaluated first); vísar = annotation-referenced Git markdown; enrollment = `siliconsaga.org/aspects` annotation. A **kennings layer** maps canonical technical terms to per-instance display lexicons (norse/plain/custom — e.g. corporate "Practice Hub"), which keeps parent-facing surfaces on plain language by construction. +Mapping introduces **no new custom kinds**: gildi = `Group` with `spec.type: guild`; skills/crafts/aspects = vocabularies; standards = Git-backed YAML for the future scorecard plugin (Tech Insights evaluated first); vísar = annotation-referenced Git markdown; enrollment = `siliconsaga.org/aspects` annotation. A **kennings layer** maps canonical technical terms to per-instance display lexicons (norse/plain/custom — e.g. corporate "Practice Hub"), which keeps parent-facing surfaces on plain language by construction. ### Consequences diff --git a/docs/demo-visir.md b/docs/demo-visir.md index 94c23fa..9efcd91 100644 --- a/docs/demo-visir.md +++ b/docs/demo-visir.md @@ -26,7 +26,7 @@ App: `http://localhost:3000` (backend on 7007). Sign in as **Guest**. First boot **Verify checklist** (run the day before a demo, not the morning of): - [ ] Catalog loads; the Kind dropdown includes **Cycle** and **Saga** -- [ ] `ravenline` Group shows the org tree (two departments — `rl-engineering`, `foxholm`) plus two `gildi`-typed Groups +- [ ] `ravenline` Group shows the org tree (two departments — `rl-engineering`, `foxholm`) plus two `guild`-typed Groups - [ ] `guild-hall` Component (type `hub`) exists, owned by `team-devex`, linking to this vísir - [ ] `security-practice` Component (type `practice`) shows its links into the aspect repo - [ ] Create page lists **Apply the Security aspect** (the adoption template) @@ -41,7 +41,7 @@ App: `http://localhost:3000` (backend on 7007). Sign in as **Guest**. First boot **2. Catalog tour (6 min).** - *Catalog → Kind dropdown*: **Cycle** and **Saga** next to Component/Group. Talking point: two custom kinds total; the entire practice layer adds **zero** more — typed Groups, vocabularies, annotations, links. -- *`ravenline` Group → relations graph*: the org tree — two departments, engineering and the acquired **Foxholm** returns line — plus two **guilds** (`spec.type: gildi`) cross-cutting it — one practice-aligned (Security), one role-aligned (Release Captains). A guild is deliberately just a typed Group: membership, rollups, and the graph come free. Point out Dagny: a Foxholm engineer in the security guild — the guild spans departments, and that's the whole point. +- *`ravenline` Group → relations graph*: the org tree — two departments, engineering and the acquired **Foxholm** returns line — plus two **guilds** (`spec.type: guild`) cross-cutting it — one practice-aligned (Security), one role-aligned (Release Captains). A guild is deliberately just a typed Group: membership, rollups, and the graph come free. Point out Dagny: a Foxholm engineer in the security guild — the guild spans departments, and that's the whole point. - *`team-devex` → `guild-hall`*: the instance you are standing in is itself cataloged (type `hub` — anticipating hub pages: singleton overviews per plugin feature group), owned by the DevEx team, and its vísir is this document. Dogfood moment. - *`security-practice` Component (type `practice`)*: the **practice** is the institution (the guild runs it); its **aspect** is the module — a repo holding the blocked standard, the paved road, the adoption templates, and the remediation docs. The entity links go straight into that repo, one click each. - *Create page → **Apply the Security aspect***: the **adoption** — applying a practice is a self-service action, not a wiki page. Run it against `label-service` (the pristine, unenrolled component): the mock edition logs its weave plan — annotation, CI includes, stewardship stubs, PR. Then the CLI beat: the same repo ships `SKILL.md`, the identical adoption for agents — *some users never leave their terminal, and neither do their agents.* diff --git a/docs/guildhall-model.md b/docs/guildhall-model.md index 69a8397..d9c7d71 100644 --- a/docs/guildhall-model.md +++ b/docs/guildhall-model.md @@ -9,7 +9,7 @@ graph TD subgraph "People layer" SKILL["Skill (vocabulary term on a person's profile)"] CRAFT["Craft / Role (skill bundle; what staffing asks for)"] - GILDI["Gildi / Guild (Group spec.type:gildi) — the fellowship"] + GILDI["Gildi / Guild (Group spec.type:guild) — the fellowship"] end subgraph "Concern layer" diff --git a/docs/plans/2026-07-10-guilds-skills-standards-design.md b/docs/plans/2026-07-10-guilds-skills-standards-design.md index ec28d2f..86b173e 100644 --- a/docs/plans/2026-07-10-guilds-skills-standards-design.md +++ b/docs/plans/2026-07-10-guilds-skills-standards-design.md @@ -133,7 +133,7 @@ Follows the established discipline: no kind introduced merely to filter; nothing | Concept | Realization | |---|---| -| Gildi | **`Group` with `spec.type: gildi`** — joins the typed-Group tree (organization/sport/…/gildi). Membership (`memberOf`), ownership rollups, and the graph come free. What the gildi stewards (craft or aspect refs) is a `siliconsaga.org/*` annotation. Dovetails with the parked CODEOWNERS-virtual-team idea: a gildi is a virtual team that is *supposed* to exist. | +| Gildi | **`Group` with `spec.type: guild`** — joins the typed-Group tree (organization/sport/…/guild). Membership (`memberOf`), ownership rollups, and the graph come free. What the gildi stewards (craft or aspect refs) is a `siliconsaga.org/*` annotation. Dovetails with the parked CODEOWNERS-virtual-team idea: a gildi is a virtual team that is *supposed* to exist. | | Skill | A **vocabulary, not entities** (Skill Exchange's exact shape): YAML-defined skill list; a profile decorator attaches selections to `User` entities so search indexes them. Matches the ResourceType-as-vocabulary precedent. | | Craft | **Vocabulary-first**: a named bundle (skill refs + vísir refs) in the same YAML family. Promotable to something heavier only if matching mechanics demand it — the cheapest commitment while the structure is still finding its shape. | | Aspect | **A repo — the module** (§3.1), holding standard(s), paved road, adoption templates, and remediation vísar together, versioned by Git itself. The registry (`aspects.yaml`, vocabulary-family) maps aspect id → module; version pins land there when module versioning gets real. No new kind — enrollment is the `siliconsaga.org/aspects` annotation on the adopting entity, and the practice's catalog face is a Component of `spec.type: practice` declared in the module's own `catalog-info.yaml` (per-repo, live-topology shape). | diff --git a/docs/plans/2026-07-20-gildi-guildhall-hub-design.md b/docs/plans/2026-07-20-gildi-guildhall-hub-design.md new file mode 100644 index 0000000..b95909e --- /dev/null +++ b/docs/plans/2026-07-20-gildi-guildhall-hub-design.md @@ -0,0 +1,142 @@ +# Leiðangr — the Guild Hall hub (`gildi` plugin) — Design + +**Date:** 2026-07-20 +**Status:** Draft +**Scope:** The first custom **frontend plugin** for this Backstage instance: `gildi`, which renders the **Guild Hall** — a designed, curated overview page for the practice layer (guilds, their practices and aspects, drives, and sagas), plus entity-page decoration for those kinds. First deliberate departure from vanilla Backstage, done idiomatically on the new frontend system. Presentation quality is a first-class goal. +**Related:** `2026-07-10-guilds-skills-standards-design.md` (the Guildhall model — practices, aspects, guilds, standards, adoption, vísar), ADRs 0007 (`Cycle`), 0008 (`Saga`), 0009/0010 (practice model, aspect-as-module, adoption's two doors), `docs/guildhall-model.md` (entity relationships), `examples/mock-org/` (the Ravenline running example this page is designed against). + +--- + +## 1. What this is, and why now + +The Guildhall model shipped as catalog data and docs; nothing yet *renders* it as a designed experience. Browsing the raw catalog — filtered tables of Groups/Components/Templates — is exactly the "drab spreadsheet" this is meant to replace. The `guild-hall` entity (`spec.type: hub`) was seeded as a placeholder anticipating this page. This design turns that anticipation into a real plugin: a **hub page** that introduces the practice layer at a glance, and a **card system** reused on entity pages when you drill in. The bar is *great presentation* — curated, human-readable cards, never a metadata dump — even at the cost of a few days' work. + +Two framing decisions set by this design: + +- The Guild Hall is **presentation, not a domain noun**. It is a plugin-contributed page, not a catalog entity. The seeded `guild-hall` `type: hub` Component **retires** (it was a placeholder for exactly this). This resolves the long-standing "a hub isn't a Kind" tension: custom Kinds stay reserved for domain nouns (`Cycle`/`Saga`); a hub is a rendered surface. +- The plugin is `gildi`; the page's display name is **"Guild Hall"**; in ordinary prose we say **"guild"**. (Old Norse flavour can skin terms later via the kennings layer.) + +## 2. Architecture and housing + +**Target the new frontend system.** This repo is on Backstage 1.52 with the new frontend system as default (`@backstage/frontend-defaults`, Blueprints, app modules) — no legacy `App.tsx` route tree. `gildi` is built with `createFrontendPlugin` (from `@backstage/frontend-plugin-api`), default-exported from `src/index.ts`, and composed via extensions from Blueprints: + +- **`PageBlueprint`** — the Guild Hall page, mounted at `/guild-hall` (route ref in `src/routes.ts`). +- **Sidebar entry** — surfaced from the `PageBlueprint`'s own `title`/`icon` (the standalone `NavItemBlueprint` was removed in `frontend-plugin-api@0.17.0`); see §9 on the eventual "Hubs" group. +- **`EntityCardBlueprint`** — the entity-page decoration cards (guild / practice / aspect), mirroring the existing `packages/app/src/modules/cycle/` card as the in-repo pattern. +- **`ApiBlueprint`** (`createApiRef` + `useApi`) — shared read/query logic and the crest generator (§5). + +Data comes exclusively through **typed catalog search** — `catalogApiRef.getEntities` with kind/type/annotation filters. This plugin introduces the first frontend catalog-querying in the repo; `@backstage/plugin-catalog-react` is already a dependency. + +**Housing: `plugins/gildi`, a real workspace package, extraction-ready.** Root `package.json` already globs `plugins/*`. We build `gildi` as a distributable package from day one — scoped package name `@siliconsaga/plugin-gildi` (introducing the `@siliconsaga` npm scope), plugin id `gildi`, instance `gildiPlugin`; depends only on public plugin APIs; imports no app-private code. leidangr remains the community/hobby *instance* (app shell + config + mock-org seed); when a second consumer appears (e.g. a corporate port) the package lifts into its own plugin-distribution repo — a relocation, not a rewrite. We do **not** create `gildi-common` or `gildi-backend` yet (YAGNI); shared constants (annotation keys, `spec.type` values) live in a single `constants.ts` until a second package needs them. + +**`Cycle` and `Saga` stay ecosystem-level kinds.** They live where they are (`packages/backend/src/modules/{cycle,saga}`), not inside `gildi`. Per the Guildhall decomposition, drives/sagas belong to the Chronicle context; the Guild Hall *queries* them (occurrences-queried-not-minted), it does not own them. Coupling them into `gildi` would make the kinds vanish if the hub weren't installed and would force a future Chronicle hub to depend on `gildi`. + +## 3. The page: five sections, swappable zones + +A single designed overview (not a rearrangeable widget grid), composed of five sections: + +1. **Intro** — a short "what the Guild Hall is" header. Room reserved for a derived graphic later. +2. **Active & upcoming drives** — a **bounded band** directly under the intro. Drives are `Cycle`s of a campaign type (default `drive`); they are inherently few (a drive with dozens of members isn't a drive), so this band never grows the page. +3. **Guilds** — the **wide primary column**, the growing list, flowing down the page as guilds are added. +4. **Chronicle** — a **rail** showing the *recent* few sagas as preview cards with a "View all sagas →"; the full, ever-growing chronicle lives on its own screen/tab later. +5. **Actions** — at the top of the rail: curated scaffolder-backed action cards (§10). + +**Swappable wide/rail zones.** Guilds and chronicle are the two growing lists; which occupies the *wide* column vs the *rail* is the natural knob. Default ships **guilds-wide** (the priority content). Because sections are config-driven (§9), an instance where the story stream matters more can flip to chronicle-wide with no rebuild. Design the two zones as swappable from the start. (Making the swap end-user-configurable is a further future extension — out of scope now.) + +**Fission-ready.** Each section is a future tab (or its own hub) under the meta-principle "a hub earns separate existence when it gains its own audience and its own editor actions." Keep the plugin's internal modules along these seams so sections → tabs → separate hubs is cheap later. Guild docs, if any, ride the entity's normal TechDocs tab — not a bespoke section. + +## 4. The card system + +Everything on the page and its entity pages shares one visual language so it reads as a single system — the antidote to filtered-catalog drabness. Every card carries: a **type tag**, a **name**, a **one-line description**, and a shared vocabulary of **chips** (practice / aspect), **avatars** (people), **crests** (guilds), progress bars, and tier badges. Whole cards link to their entity page. + +**The identity-mark rule (one rule, applied everywhere):** each card leads with an identity mark — + +- a **guild crest** when a guild is the card's actor / steward / subject (guild, practice, drive, and a saga that involves a guild all lead with the relevant guild's crest); +- a **person's avatar** when the card is person-led (a personal saga leads with its skald's avatar); +- a **scaffolder glyph** for action cards. + +Card-specific elements ride alongside the identity mark (a drive's progress bar, an aspect's tier ladder) — that variety is welcome; only the *leading mark* is invariant. + +**The family:** guild, practice, aspect, component (adopter), drive, saga preview, action. Practice/aspect cards double as the entity-page decoration cards when you drill in. Curated content only — clean display names and a brief description, never raw metadata; an entity search may appear as a styled widget but never as the primary surface. + +## 5. Generated heraldic crests + +Each guild gets a **generated coat of arms** — GitHub-identicon energy, but a real heraldic device — giving every guild an instant, memorable identity (you recognise a guild by its arms before reading the name), and a brand-new guild has a device the moment it exists. + +- **Deterministic from the guild id.** Hash the id → pick a field division (plain / per pale / per fess / per bend / quarterly), two tinctures from the heraldic palette (respecting the rule of tincture — colour-on-metal / metal-on-colour), and a charge (key, chevron, mullet, roundel, cross, lion, …). Render as **inline SVG** — no art assets, no external calls. +- **Deliberately simple.** Recognizability over ornament; over-complex arms lose the at-a-glance identicon quality. Keep charges bold and few. +- **Escape hatches.** An annotation (e.g. `siliconsaga.org/arms`) overrides with a hand-picked blazon or image; a plain **monogram** is the fallback if generation is disabled. +- **Self-contained module.** Isolated enough to be its own small piece so other hubs (a future people hub, etc.) reuse it. **v1 renders crests for guilds only** — the generator works on any `Group`, so non-guild teams could carry arms later, but that stays out of v1. + +## 6. Annotation-driven decoration (cross-kind) + +A general mechanism, not guild-only: sections/cards populate their content from **catalog annotations**, so authors enrich pages by editing catalog YAML — the same pattern Cervator used on a team home page previously. Applies across kinds (guild, practice, aspect, saga, cycle). + +- **Prose, two grades (start inline, grow to referenced):** a short blurb lives in `metadata.description` (or a custom annotation); a richer body is a **referenced markdown doc** the card fetches and renders — reusing the existing `siliconsaga.org/saga-doc` convention. Ships inline-first; referenced markdown lands as conventions mature. +- **Front-matter preview cards.** A referenced markdown (a saga, a guild charter) carries front-matter (title, summary, author/skald, date, optional hero); the card renders a **preview** from the front-matter and links out to the full experience (TechDocs, or an external blog). This "preview card" shape is reused for sagas and for charter/mission bodies. +- **Guild entity-page decoration.** The guild's own page gets decorated from its catalog file: charter/mission prose, stewards (`siliconsaga.org/stewards`), featured links (native `metadata.links`), its practices + aspects (from relations/queries), and highlighted recent sagas/drives. The *richer* guild detail lives here, on the entity page — the hub's guild card is the compact glimpse that links in. + +## 7. Data-model touchpoints and the guild-type rename + +The plugin reads existing shapes via typed search — it mints nothing: + +- **Guilds** = `Group` with **`spec.type: guild`** (queried `kind:group, spec.type:guild`). *Preliminary data change:* the seed currently types guild Groups as `gildi`; rename the **group type** `gildi` → `guild` across the seed (`org.yaml`), the smoke assertions, and doc references (a small sweep, sibling to the graft→adoption rename). "gildi" survives only as the plugin/package name; Old Norse group-type flavour can return later via kennings. +- **Practices** = `Component` `spec.type: practice` (owned by the stewarding guild). +- **Aspects** = **adoption** `Template`s (`spec.type: aspect`), which are ingested and queryable. +- **Drives** = `Cycle`s of a campaign type (default `drive`; the set is config-driven, §9). +- **Sagas** = `Saga` entities (front-matter body via `siliconsaga.org/saga-doc`). +- **Adopters/badges** = `Component`s carrying enrollment annotations (`siliconsaga.org/aspects`, `…/aspect-versions`, `…/adoption-record`). + +## 8. The aspect ladder and the component badge + +A modeling truth the card system must reflect: an **aspect does not have a badge**. It holds a **standard** with a **tier ladder** (bronze / silver / gold) — the rungs to climb. A **component** that adopts the aspect **earns** a tier by passing the standard's trials; the badge lives on the *component*, not the aspect. Aspect cards therefore show the *ladder*; component cards (and component entity pages) show the *earned badge*. + +**Deferred — differentiating the ladder (noted, not needed for a while).** A bare bronze→silver→gold ladder looks identical on every aspect. When the data exists, distinguish aspects on their aspect card by either (or both): (a) the **count of trials/checks** required for each tier — available once trial evaluation is implemented; or (b) **adoption stats** — how many components have enrolled in the aspect and how many reached each tier. A knock-on: a guild card could roll up "its components at bronze/silver/gold" as a maturity glance. All of this is post-MVP; trial evaluation and adoption stats are not implemented today (bronze/silver in the seed is demo narrative). + +## 9. Customization via extension config + +The hub page's customization surface is **extension config** in `app-config.yaml` (the new frontend system's native per-extension config; the app already uses one to remount the catalog at `/`). Admins reconfigure structure with zero code: + +- intro heading/blurb; +- which sections show and in what order (including the guilds↔chronicle wide/rail swap); +- which `Cycle` types count as "drives"; +- how many chronicle previews and which tag sources actions. + +**Deferred:** making the intro *content* author-editable from the catalog (rather than admin config) via a referenced markdown — added later once decoration conventions are proven on guild pages; not a reason to keep a hub entity. The sidebar's eventual **"Hubs" item group** (with "Guild Hall" the first entry) is anticipated but, until a second hub exists, "Guild Hall" can sit as a top-level nav item. + +## 10. Actions — scaffolder links, tag-sourced + +The Actions section is **links to Scaffolder Templates** (the idiomatic Backstage "Create" surface), not bespoke buttons — so "establish a new guild", "charter a practice", "start a drive" ride the same adoption/two-door machinery rather than being special-cased. The hub surfaces Templates **by a convention tag `guild-hall`** — a lowercase slug (tags render in filter chips / URLs and are never the user-facing label; the action card's friendly name comes from the Template *title*, so "Guild Hall" stays the display and the tag stays a tidy identifier). Tag-based discovery is least-coupling and composes with owner-based discovery later. Dogfooding falls out cleanly: **running a guild hall is itself a practice**, so the guild hall's operational scaffolders are the adoption templates of the guild hall's own practice. **v1 ships at least a light dogfood**: a `guildhall` practice + its aspect (with one or two mock adoption Templates tagged `guild-hall`), so the hub demonstrably runs on its own model rather than only describing it. + +## 11. Mermaid via the TechDocs Addons framework + +Adopt the community TechDocs **Addons** mermaid addon (`backstage-plugin-techdocs-addon-mermaid`) so existing ```` ```mermaid ```` fences (in root `docs/guildhall-model.md` and elsewhere) render client-side inside TechDocs' shadow DOM — the path already flagged in `mkdocs.yml` and the demo retro. This replaces the intentionally-removed `mkdocs-mermaid2` plugin (absent from the Docker generator image, shadow-DOM-blocked). Verify currency of the addon against the installed TechDocs version before wiring. **Prioritized:** it's small, self-contained, and independent of the rest of the plugin, so land it **as early as practical** (its own step is fine) — the concept diagrams should render in-product as soon as we can. + +## 12. Scope and phasing + +Multi-day is acceptable; presentation is the priority. Rough order (each a shippable slice): + +1. **Scaffold `plugins/gildi`** (new-frontend-system plugin, page route + sidebar item, empty page) + retire the `guild-hall` Component + the `gildi`→`guild` group-type seed rename. +2. **Crest module** (generated heraldic SVG from group id) — the visual keystone; unit-tested for determinism + tincture rules. +3. **Guilds section** — typed catalog query + the guild card (crest, description, stewards, practice/aspect chips), the wide growing column. +4. **Drives band + Chronicle rail** — drive cards (progress) and saga preview cards (front-matter), swappable zones. +5. **Actions + the `guildhall` dogfood** — tag-sourced (`guild-hall`) scaffolder-link action cards, plus the light dogfood: a `guildhall` practice + aspect with one or two mock adoption Templates so the hub runs on its own model. +6. **Entity-page decoration** — guild page (annotation-driven charter/links/roster), practice & aspect cards (aspect shows the tier ladder; component shows the earned badge). +7. **Mermaid TechDocs addon** — independent of the plugin; land **early / in parallel** (prioritized, §11), not last. + +## 13. Out of scope / deferred / fast-follows + +- **App home page** (`@backstage/plugin-home`) — moving the catalog off `/` to a real welcome/starred/toolkit home is a **separate sibling fast-follow**, not part of `gildi`; the hub shares its "gentle landing" ethos but is a distinct designed page. +- User-configurable wide/rail swap; `gildi-common`/`gildi-backend` packages; catalog-backed hub content; extraction to a standalone plugin repo (and the future naming of that workspace — *not* committing to "kaupang"); ladder differentiation (§8); trial evaluation / adoption execution (designed-not-implemented upstream). + +## 14. Testing + +- **Crest generator:** unit tests for determinism (same id → same arms) and rule-of-tincture adherence. +- **Cards/page:** `renderInTestApp` / `createExtensionTester` (from `@backstage/frontend-test-utils`, already a dev dep) with a mocked `catalogApi` returning seed-shaped entities; assert curated content renders (names, chips, identity marks) and empty states are graceful. +- **Seed:** extend `make smoke-catalog` for the `guild`-typed Group assertion (replacing the `gildi` type check); the full `make ci` gate (config-check + lint + tsc + tests) covers the plugin build. + +## 15. Decisions and open questions + +**Resolved in review (2026-07-20):** action discovery tag = **`guild-hall`** (a slug; "Guild Hall" remains the display, sourced from the Template title); **crests are guilds-only in v1** (non-guild teams may get arms later); the **`guildhall` dogfood practice + aspect ships in v1**; **Mermaid is prioritized** to land early and independently. + +**Still open (detail, non-blocking):** the exact heraldic charge set and tincture palette — kept deliberately small for recognizability; pin it during the crest slice (§12.2). diff --git a/docs/plans/2026-07-20-gildi-guildhall-hub-plan.md b/docs/plans/2026-07-20-gildi-guildhall-hub-plan.md new file mode 100644 index 0000000..6efc4c7 --- /dev/null +++ b/docs/plans/2026-07-20-gildi-guildhall-hub-plan.md @@ -0,0 +1,277 @@ +# Guild Hall hub (`gildi`) — Plan 1: Foundation + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Stand up the `gildi` plugin as a mounted, sidebar-linked (empty) Guild Hall page on the new frontend system, get Mermaid rendering in TechDocs, and rename the guild **group type** `gildi` → `guild` — the prerequisites every later slice builds on. + +**Architecture:** A new workspace package `plugins/gildi` exposes a `createFrontendPlugin` default export with a `PageBlueprint` (route `/guild-hall`, whose `title`/`icon` also provide the sidebar entry — the standalone `NavItemBlueprint` was removed in frontend-plugin-api 0.17.0); the app registers it in `packages/app/src/App.tsx` `features`. Mermaid is wired via the TechDocs Addons framework. The seed's guild Groups switch `spec.type: gildi` → `guild`. No catalog querying or cards yet — that is Plan 2+. + +**Tech Stack:** Backstage 1.52 (new frontend system), `@backstage/frontend-plugin-api@^0.17.2`, `@backstage/plugin-catalog-react@^3.1.0`, `@backstage/frontend-test-utils@^0.6.1`, TypeScript ~5.8, React 18, Yarn 4.13 (Corepack). + +## Global Constraints + +- Node **22 || 24**; Yarn **4.13** via Corepack (`corepack yarn …`). Never raw `npm`. +- **New frontend system only** — `createFrontendPlugin` + Blueprints; no legacy `createApp`/`FlatRoutes`/`EntityPage`. +- Package scope **`@siliconsaga`**; plugin id **`gildi`**; instance **`gildiPlugin`**; sidebar display **"Guild Hall"**; license field **UNLICENSED**. +- Guild Groups use **`spec.type: guild`** (never `gildi`); "gildi" survives only as the plugin/package name. Group *names* (`security-gildi`, `release-captains-gildi`) are unchanged in this plan. +- Run builds/tests through `ws`: `ws test leidangr` (= `make ci`), `ws exec leidangr make smoke-catalog`, `ws exec leidangr corepack yarn tsc`. Commit via `ws commit leidangr `. +- Design source of truth: `docs/plans/2026-07-20-gildi-guildhall-hub-design.md`. +- Before writing Blueprint code, cross-check current signatures against the installed `@backstage/frontend-plugin-api@0.17.2` and the Backstage "Building Frontend Plugins" docs — the `tsc`/build gates below catch any drift. + +--- + +### Task A: Rename guild group type `gildi` → `guild` + +**Files:** +- Modify: `examples/mock-org/org.yaml` (the two guild Groups' `spec.type`) +- Modify: `scripts/smoke-catalog.sh` (the type assertion) +- Modify (label/type references only): `docs/guildhall-model.md`, `docs/demo-visir.md`, `examples/mock-org/README.md`, `docs/plans/2026-07-10-guilds-skills-standards-design.md`, `docs/adrs/0009-guildhall-practice-model.md` +- Test: `scripts/smoke-catalog.sh` (existing runtime proof) + +**Interfaces:** +- Produces: guild Groups queryable as `kind:group, spec.type:guild` — the filter Plan 2's Guilds section relies on. + +- [ ] **Step 1: Find every occurrence of the type, separating type-value from concept/name.** + +Run: `rg -n "gildi" .` (via the Grep tool, from the repo root). Classify each hit: **rename** only where it is the *type value* (`spec.type: gildi`, "type `gildi`", "`spec.type:gildi`", "gildi-typed"); **leave** group *names* (`security-gildi`, `release-captains-gildi`), the plugin/concept word "gildi", and the `-gildi` suffixes in refs. + +- [ ] **Step 2: Change the two Groups' type in the seed.** + +In `examples/mock-org/org.yaml`, both guild Groups: `spec: { type: gildi, … }` → `spec: { type: guild, … }` (only the `type:` field; `parent`, `children`, `name`, the `siliconsaga.org/stewards` annotation are unchanged). + +- [ ] **Step 3: Update the smoke assertion to expect `guild`.** + +In `scripts/smoke-catalog.sh`, the gildi check currently asserts `'"type":"gildi"'`. Change its label and value to `guild`: +```sh +check "Guild Group ingested (type guild)" "$GILDI" '"type":"guild"' || pass=0 +``` +(The `GILDI` shell variable name may stay or be renamed to `GUILD` for clarity — if renamed, update its three uses: the init line, the `byname group/default/security-gildi` capture, and the readiness `grep`.) + +- [ ] **Step 4: Sweep type-value references in docs (not names/concept).** + +Update only the type-citing phrases, e.g. in `docs/guildhall-model.md` the Mermaid node `Group spec.type:gildi` → `Group spec.type:guild`; in `docs/demo-visir.md` "two `gildi`-typed Groups" → "two `guild`-typed Groups" and "(`spec.type: gildi`)" → "(`spec.type: guild`)"; in `examples/mock-org/README.md` "gildi Groups (`spec.type: gildi`)" → "guild Groups (`spec.type: guild`)"; in the 2026-07-10 design §5 mapping row "`Group` with `spec.type: gildi`" → "`spec.type: guild`". Leave the institution word "gildi", the ADR/kenning discussions, and group names intact. + +- [ ] **Step 5: Run the smoke test — it must still pass, now on `guild`.** + +Run: `ws exec leidangr make smoke-catalog` +Expected: `smoke-catalog PASS`, including `PASS Guild Group ingested (type guild)`. + +- [ ] **Step 6: Commit.** + +Write `.commits/gildi-guild-type-rename.md` (frontmatter `add:` the five modified files) and run: +```bash +ws commit leidangr .commits/gildi-guild-type-rename.md +``` +Message: `refactor(seed): rename guild group type gildi → guild`. + +--- + +### Task B: Scaffold the `gildi` plugin — mounted page + sidebar item + +**Files:** +- Create: `plugins/gildi/package.json` +- Create: `plugins/gildi/tsconfig.json` +- Create: `plugins/gildi/src/routes.ts` +- Create: `plugins/gildi/src/plugin.tsx` +- Create: `plugins/gildi/src/components/GuildHallPage.tsx` +- Create: `plugins/gildi/src/index.ts` +- Create: `plugins/gildi/src/plugin.test.tsx` +- Modify: `packages/app/src/App.tsx` (register `gildiPlugin`) +- Modify: `packages/app/src/modules/nav/Sidebar.tsx` (surface the nav item in the Menu group) + +**Interfaces:** +- Produces: default export `gildiPlugin` (a `FrontendPlugin`); a route ref `rootRouteRef` at `/guild-hall`; component `GuildHallPage`. Plan 2 attaches sections inside `GuildHallPage` and adds `EntityCardBlueprint` extensions to `gildiPlugin`. + +- [ ] **Step 1: Create the package manifest** (`plugins/gildi/package.json`) — mirror the app package's Backstage role/scripts, scope `@siliconsaga`, role `frontend-plugin`: +```json +{ + "name": "@siliconsaga/plugin-gildi", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "UNLICENSED", + "private": true, + "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { "role": "frontend-plugin", "pluginId": "gildi", "pluginPackages": ["@siliconsaga/plugin-gildi"] }, + "sideEffects": false, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean" + }, + "dependencies": { + "@backstage/core-components": "^0.18.11", + "@backstage/frontend-plugin-api": "^0.17.2", + "@backstage/plugin-catalog-react": "^3.1.0", + "@backstage/ui": "^0.16.0", + "@material-ui/icons": "^4.9.1", + "react-router-dom": "^6.30.2" + }, + "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" }, + "devDependencies": { + "@backstage/cli": "^0.36.3", + "@backstage/frontend-test-utils": "^0.6.1", + "@testing-library/react": "^14.0.0" + }, + "files": ["dist"] +} +``` + +- [ ] **Step 2: Add the package tsconfig** (`plugins/gildi/tsconfig.json`): +```json +{ "extends": "@backstage/cli/config/tsconfig.json", "include": ["src", "dev", "migrations"], "exclude": ["node_modules"], "compilerOptions": { "outDir": "dist", "rootDir": "." } } +``` + +- [ ] **Step 3: Define the route ref** (`plugins/gildi/src/routes.ts`): +```ts +import { createRouteRef } from '@backstage/frontend-plugin-api'; + +export const rootRouteRef = createRouteRef(); +``` + +- [ ] **Step 4: Write the placeholder page component** (`plugins/gildi/src/components/GuildHallPage.tsx`) — real headers now, sections land in Plan 2: +```tsx +import { Content, Header, Page } from '@backstage/core-components'; + +export function GuildHallPage() { + return ( + +
+ +

The Guild Hall is taking shape. Guilds, drives, chronicle, and actions arrive next.

+
+ + ); +} +``` + +- [ ] **Step 5: Write the plugin with its page extension** (`plugins/gildi/src/plugin.tsx`). As-built: `NavItemBlueprint` was removed in `@backstage/frontend-plugin-api@0.17.0`, so the sidebar entry is discovered from the `PageBlueprint`'s own `title`/`icon` — one blueprint, no separate nav item: +```tsx +import { createFrontendPlugin, PageBlueprint } from '@backstage/frontend-plugin-api'; +import ShieldIcon from '@material-ui/icons/Security'; +import { rootRouteRef } from './routes'; + +const guildHallPage = PageBlueprint.make({ + params: { + path: '/guild-hall', + title: 'Guild Hall', + icon: , + routeRef: rootRouteRef, + loader: () => import('./components/GuildHallPage').then(m => ), + }, +}); + +export const gildiPlugin = createFrontendPlugin({ + pluginId: 'gildi', + extensions: [guildHallPage], + routes: { root: rootRouteRef }, +}); +``` +(Historical note: this was originally drafted with a separate `NavItemBlueprint` + `defaultPath`; the 0.17.x API folds nav into `PageBlueprint` via `path`/`title`/`icon`. The Step 8 build is the gate that caught it.) + +- [ ] **Step 6: Export the plugin as the default** (`plugins/gildi/src/index.ts`): +```ts +export { gildiPlugin as default } from './plugin'; +``` + +- [ ] **Step 7: Write the failing render test** (`plugins/gildi/src/plugin.test.tsx`): +```tsx +import { screen } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { GuildHallPage } from './components/GuildHallPage'; + +describe('GuildHallPage', () => { + it('renders the Guild Hall header', async () => { + await renderInTestApp(); + expect(await screen.findByText('Guild Hall')).toBeInTheDocument(); + }); +}); +``` + +- [ ] **Step 8: Install + build + test the package in isolation.** + +Run: `ws exec leidangr corepack yarn install` +Then: `ws exec leidangr corepack yarn workspace @siliconsaga/plugin-gildi tsc` +Then: `ws exec leidangr corepack yarn workspace @siliconsaga/plugin-gildi test` +Expected: install picks up the new workspace; `tsc` clean; the render test PASSES. Fix import/param drift against the installed API until green. + +- [ ] **Step 9: Register the plugin in the app** (`packages/app/src/App.tsx`): +```tsx +import { createApp } from '@backstage/frontend-defaults'; +import catalogPlugin from '@backstage/plugin-catalog/alpha'; +import gildiPlugin from '@siliconsaga/plugin-gildi'; +import { navModule } from './modules/nav'; +import { cycleModule } from './modules/cycle'; + +export default createApp({ + features: [catalogPlugin, gildiPlugin, navModule, cycleModule], +}); +``` +Add `"@siliconsaga/plugin-gildi": "^0.1.0"` to `packages/app/package.json` dependencies, then re-run `ws exec leidangr corepack yarn install`. + +- [ ] **Step 10: Ensure the sidebar shows "Guild Hall".** The nav renders `nav.rest({ sortBy: 'title' })` inside the Menu group (`Sidebar.tsx:38-40`), so the `PageBlueprint`'s `title`/`icon` surface as a sidebar item automatically — no edit needed. (If you ever want it pinned above `nav.rest`, `nav.take()` after `nav.take('page:scaffolder')`, confirming the id with the app-visualizer.) + +- [ ] **Step 11: Verify the whole app builds and the page mounts.** + +Run: `ws test leidangr` (full `make ci`: config-check + lint + tsc + tests) +Expected: PASS. +Then boot for a visual check: `ws exec leidangr make dev`, open `http://localhost:3000`, confirm **"Guild Hall"** appears in the sidebar and routes to the page at `/guild-hall`. (Human-gated visual confirmation.) + +- [ ] **Step 12: Commit.** + +`.commits/gildi-scaffold.md` staging `plugins/gildi/`, `packages/app/src/App.tsx`, `packages/app/package.json` (and `Sidebar.tsx` if edited). Run `ws commit leidangr .commits/gildi-scaffold.md`. +Message: `feat(gildi): scaffold the Guild Hall plugin — mounted page + sidebar item`. + +--- + +### Task C: Render Mermaid in TechDocs (Addons framework) + +**Files:** +- Modify: `packages/app/package.json` (add the mermaid addon dependency) +- Create/Modify: a small techdocs-addons app module (new frontend system) — exact wiring determined by Step 1 +- Test: manual TechDocs render of `docs/guildhall-model.md` + +**Interfaces:** +- Produces: ```` ```mermaid ```` fences in any TechDocs site render as diagrams (unblocks the root guildhall-model.md concept maps). + +- [ ] **Step 1: Confirm addon + new-frontend-system compatibility (spike, timeboxed).** + +Check the current `backstage-plugin-techdocs-addon-mermaid` (or the equivalent maintained addon) for **new frontend system support** and its registration shape. The app already depends on `@backstage/plugin-techdocs-module-addons-contrib`, which is the addon-wiring seam. Read the addon's README + the Backstage TechDocs Addons docs. Record the exact package name/version and whether it exposes a new-frontend-system extension or needs the legacy `TechDocsAddons` compat wrapper. **If it has no new-frontend-system path yet, stop and report** — we choose between the legacy-compat wrapper and deferring (fences keep degrading to code blocks; not a blocker for the rest of the plugin). + +- [ ] **Step 2: Add the dependency.** + +Add the confirmed addon package+version to `packages/app/package.json`, then `ws exec leidangr corepack yarn install`. + +- [ ] **Step 3: Wire the addon per Step 1's finding** (exact code from the addon's new-frontend-system docs — a techdocs addon extension registered in an app module or the plugin's features). + +- [ ] **Step 4: Render-verify against the root concept map.** + +Run: `ws exec leidangr make dev` with local TechDocs (`app-config.local.yaml` → `techdocs.generator.runIn: local`, `pip install mkdocs-techdocs-core`). Open the Guild Hall / root TechDocs site and confirm the `guildhall-model.md` Mermaid diagrams render as diagrams, not code blocks. (Human-gated visual confirmation.) + +- [ ] **Step 5: Commit.** + +`.commits/gildi-mermaid-addon.md`. Message: `feat(techdocs): render mermaid via the TechDocs Addons framework`. + +--- + +### Decision (made 2026-07-20) — retire the `guild-hall` Component by re-homing its docs (Option 1) + +Cervator's pick: **re-home, not demote.** The `guild-hall` `type: hub` Component is retired and its root TechDocs re-homed. That entity currently anchors `docs/guildhall-model.md` + root `mkdocs.yml` via `backstage.io/techdocs-ref: dir:.` (a `dir:.` ref can only anchor an entity whose file sits at the repo root — and `catalog-info.yaml` is the only root entity), carries `siliconsaga.org/visir: docs/demo-visir.md`, and is referenced by `docs/demo-visir.md`, `examples/mock-org/README.md`, and the app-config location at `app-config.yaml:132-135`. + +The retirement is **its own later plan** (it must run *after* the Guild Hall page is real, so the docs have somewhere to land). That plan will: +1. **Re-home the model docs onto the Guild Hall experience** — surface the `guildhall-model.md` concept map on the plugin's page (mermaid-in-app, leaning on the Task C addon or an in-page mermaid render) and/or move the root `mkdocs.yml` docs to plugin-scoped docs, so the model overview lives with the hub it describes rather than a placeholder entity. Re-home the vísir link too. +2. **Delete the `guild-hall` entity** — remove root `catalog-info.yaml`, its `app-config.yaml` catalog location (lines 130-135), and sweep the `guild-hall` references in `demo-visir.md` / `examples/mock-org/README.md`. +3. **Verify** — update `make smoke-catalog` so it no longer expects the hub entity; confirm the concept map still renders (now in-app) and no TechDocs 404s. + +Not part of Plan 1 (Plan 1's page is the prerequisite). Captured here so the sequencing is unambiguous. + +--- + +## Self-Review + +- **Spec coverage (Plan 1 scope):** new-frontend-system scaffold (design §2) → Task B; guild-type rename (§7) → Task A; Mermaid addon (§11) → Task C; `guild-hall` retirement (§1/§12) → surfaced as a Decision (blocked on a choice, correctly not fabricated). Crest module, catalog-querying cards, drives/chronicle/actions, entity decoration, dogfood (§4–§10) are **out of Plan 1 scope** — they are Plan 2+. +- **Placeholder scan:** Task C Steps 2–3 depend on Step 1's spike output (the addon's exact package + wiring can't be pinned without checking its new-frontend-system support) — this is a genuine investigation gate, flagged as such, not a lazy placeholder. Everything in Tasks A and B is exact. +- **Type consistency:** `gildiPlugin` (default export), `rootRouteRef`, `GuildHallPage` used consistently across plugin.tsx / index.ts / App.tsx / test. +- **Blueprint-API caveat:** `PageBlueprint`/`NavItemBlueprint` param shapes are per the documented new-frontend-system API; the Step-8 `tsc`/build gate is the safety net for version drift, with an explicit adjust-if-different note. diff --git a/examples/mock-org/README.md b/examples/mock-org/README.md index 6e59eaf..af0e0c3 100644 --- a/examples/mock-org/README.md +++ b/examples/mock-org/README.md @@ -36,10 +36,10 @@ The `guildhall/` tree and most of `repos/` are **plain YAML/markdown, deliberate | Ingests today (catalog) | Waits for plugins | |---|---| -| Org tree, gildi Groups (`spec.type: gildi`), Users | Skill profiles decorating Users | +| Org tree, guild Groups (`spec.type: guild`), Users | Skill profiles decorating Users | | Software graph, enrollment + vísir annotations (inert but present) | Standards evaluation / scorecards (Tech Insights or custom) | | `Cycle` (release + drive) and `Saga` with relations | Runbooks plugin (parameterized vísar) | Until the scorecard engine exists, the **practice → aspect → standard → trials tie is navigational**: the `security-practice` Component's and `security-gildi` Group's entity links jump straight into the aspect repo — standard, paved road, adoption templates, remediation docs. The scorecard plugin later turns that chain into live data on entity pages. The adoption template renders on the **Create page** today (it logs its weave plan rather than opening a real PR — designed-not-executed, like the ratings). -`make smoke-catalog` asserts the mock org ingests at runtime alongside the MTL seed (gildi Group typed, release Cycle with its relations, the Saga touching it). +`make smoke-catalog` asserts the mock org ingests at runtime alongside the MTL seed (guild Group typed, release Cycle with its relations, the Saga touching it). diff --git a/examples/mock-org/org.yaml b/examples/mock-org/org.yaml index b11c227..d073a85 100644 --- a/examples/mock-org/org.yaml +++ b/examples/mock-org/org.yaml @@ -71,7 +71,7 @@ metadata: - url: https://github.com/SiliconSaga/leidangr/blob/main/examples/mock-org/repos/security-aspect/template.yaml title: Adoption — Apply the Security aspect spec: - type: gildi + type: guild parent: ravenline children: [] --- @@ -83,7 +83,7 @@ metadata: annotations: siliconsaga.org/stewards: 'craft:release-captain' spec: - type: gildi + type: guild parent: ravenline children: [] --- diff --git a/mkdocs.yml b/mkdocs.yml index b3a7d9a..c37950a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,10 +17,5 @@ nav: - 0008 — Saga git-backed kind: adrs/0008-saga-git-backed-kind.md - 0009 — Guildhall practice model: adrs/0009-guildhall-practice-model.md - 0010 — Aspect module, adoption, blocks: adrs/0010-aspect-module-adoption-blocks.md -# Mermaid fences render as plain code blocks for now: the mermaid2 plugin's div -# output can't render inside TechDocs' shadow DOM anyway, and it is absent from -# the default TechDocs Docker generator image (breaking `runIn: docker` builds). -# The planned TechDocs Addons mermaid addon renders client-side from these -# fences without any mkdocs-side plugin. plugins: - techdocs-core diff --git a/package.json b/package.json index 02b439a..8fa601e 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,9 @@ }, "resolutions": { "@types/react": "^18", - "@types/react-dom": "^18" + "@types/react-dom": "^18", + "@backstage/frontend-plugin-api": "^0.17.2", + "@backstage/plugin-techdocs-react": "^1.3.12" }, "prettier": "@backstage/cli/config/prettier", "lint-staged": { diff --git a/packages/app/package.json b/packages/app/package.json index a00051a..a6606b5 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -41,6 +41,8 @@ "@backstage/ui": "^0.16.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", + "@siliconsaga/plugin-gildi": "^0.1.0", + "backstage-plugin-techdocs-addon-mermaid": "^0.26.0", "react": "^18.0.2", "react-dom": "^18.0.2", "react-router": "^6.30.2", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 0a472ff..ce9e5ba 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -1,8 +1,9 @@ import { createApp } from '@backstage/frontend-defaults'; import catalogPlugin from '@backstage/plugin-catalog/alpha'; +import gildiPlugin from '@siliconsaga/plugin-gildi'; import { navModule } from './modules/nav'; import { cycleModule } from './modules/cycle'; export default createApp({ - features: [catalogPlugin, navModule, cycleModule], + features: [catalogPlugin, gildiPlugin, navModule, cycleModule], }); diff --git a/plugins/gildi/.eslintrc.js b/plugins/gildi/.eslintrc.js new file mode 100644 index 0000000..e2a53a6 --- /dev/null +++ b/plugins/gildi/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/gildi/package.json b/plugins/gildi/package.json new file mode 100644 index 0000000..4b4ba68 --- /dev/null +++ b/plugins/gildi/package.json @@ -0,0 +1,49 @@ +{ + "name": "@siliconsaga/plugin-gildi", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "UNLICENSED", + "private": true, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin", + "pluginId": "gildi", + "pluginPackages": [ + "@siliconsaga/plugin-gildi" + ] + }, + "sideEffects": false, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean" + }, + "dependencies": { + "@backstage/core-components": "^0.18.11", + "@backstage/frontend-plugin-api": "^0.17.2", + "@backstage/plugin-catalog-react": "^3.1.0", + "@backstage/ui": "^0.16.0", + "@material-ui/icons": "^4.9.1", + "react-router-dom": "^6.30.2" + }, + "peerDependencies": { + "react": "^17 || ^18", + "react-dom": "^17 || ^18" + }, + "devDependencies": { + "@backstage/cli": "^0.36.3", + "@backstage/frontend-test-utils": "^0.6.1", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/gildi/src/components/GuildHallPage.tsx b/plugins/gildi/src/components/GuildHallPage.tsx new file mode 100644 index 0000000..9aacbaf --- /dev/null +++ b/plugins/gildi/src/components/GuildHallPage.tsx @@ -0,0 +1,12 @@ +import { Content, Header, Page } from '@backstage/core-components'; + +export function GuildHallPage() { + return ( + +
+ +

The Guild Hall is taking shape. Guilds, drives, chronicle, and actions arrive next.

+
+ + ); +} diff --git a/plugins/gildi/src/index.ts b/plugins/gildi/src/index.ts new file mode 100644 index 0000000..177505c --- /dev/null +++ b/plugins/gildi/src/index.ts @@ -0,0 +1 @@ +export { gildiPlugin as default } from './plugin'; diff --git a/plugins/gildi/src/plugin.test.tsx b/plugins/gildi/src/plugin.test.tsx new file mode 100644 index 0000000..eea0b81 --- /dev/null +++ b/plugins/gildi/src/plugin.test.tsx @@ -0,0 +1,10 @@ +import { screen } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { GuildHallPage } from './components/GuildHallPage'; + +describe('GuildHallPage', () => { + it('renders the Guild Hall header', async () => { + await renderInTestApp(); + expect(await screen.findByText('Guild Hall')).toBeInTheDocument(); + }); +}); diff --git a/plugins/gildi/src/plugin.tsx b/plugins/gildi/src/plugin.tsx new file mode 100644 index 0000000..f05fc80 --- /dev/null +++ b/plugins/gildi/src/plugin.tsx @@ -0,0 +1,22 @@ +import { createFrontendPlugin, PageBlueprint } from '@backstage/frontend-plugin-api'; +import ShieldIcon from '@material-ui/icons/Security'; +import { rootRouteRef } from './routes'; + +// NOTE: `NavItemBlueprint` was removed in @backstage/frontend-plugin-api@0.17.0 +// (BREAKING). Nav items are now discovered from `PageBlueprint` extensions via +// their `title`/`icon` params, so the page below doubles as the sidebar entry. +const guildHallPage = PageBlueprint.make({ + params: { + path: '/guild-hall', + title: 'Guild Hall', + icon: , + routeRef: rootRouteRef, + loader: () => import('./components/GuildHallPage').then(m => ), + }, +}); + +export const gildiPlugin = createFrontendPlugin({ + pluginId: 'gildi', + extensions: [guildHallPage], + routes: { root: rootRouteRef }, +}); diff --git a/plugins/gildi/src/routes.ts b/plugins/gildi/src/routes.ts new file mode 100644 index 0000000..559a9cc --- /dev/null +++ b/plugins/gildi/src/routes.ts @@ -0,0 +1,3 @@ +import { createRouteRef } from '@backstage/frontend-plugin-api'; + +export const rootRouteRef = createRouteRef(); diff --git a/plugins/gildi/src/setupTests.ts b/plugins/gildi/src/setupTests.ts new file mode 100644 index 0000000..7b0828b --- /dev/null +++ b/plugins/gildi/src/setupTests.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/plugins/gildi/tsconfig.json b/plugins/gildi/tsconfig.json new file mode 100644 index 0000000..0f4ebaa --- /dev/null +++ b/plugins/gildi/tsconfig.json @@ -0,0 +1 @@ +{ "extends": "@backstage/cli/config/tsconfig.json", "include": ["src", "dev", "migrations"], "exclude": ["node_modules"], "compilerOptions": { "outDir": "dist", "rootDir": "." } } diff --git a/scripts/smoke-catalog.sh b/scripts/smoke-catalog.sh index 721ab18..11e6f39 100644 --- a/scripts/smoke-catalog.sh +++ b/scripts/smoke-catalog.sh @@ -128,12 +128,12 @@ check_rel "Saga ownedBy owner (mtl-soccer)" "$SAGA" ownedBy group:default/mtl check_rel "Saga dependsOn Cycle (touches)" "$SAGA" dependsOn cycle:default/soccer-2026-spring || pass=0 check "Saga doc annotation preserved" "$SAGA" 'siliconsaga.org/saga-doc' || pass=0 # Mock software org (Ravenline — Guildhall running example): the software -# side of the two-family model plus a gildi-typed Group, ingesting with the +# side of the two-family model plus a guild-typed Group, ingesting with the # same machinery and zero new code. check "Ravenline Cycle ingested (release)" "$RLCYCLE" '"type":"release"' || pass=0 check_rel "Ravenline Cycle partOf parcel-tracking" "$RLCYCLE" partOf system:default/parcel-tracking || pass=0 check_rel "Ravenline Cycle dependsOn prod-cluster" "$RLCYCLE" dependsOn resource:default/prod-cluster || pass=0 -check "Gildi Group ingested (type gildi)" "$GILDI" '"type":"gildi"' || pass=0 +check "Guild Group ingested (type guild)" "$GILDI" '"type":"guild"' || pass=0 check "Guild Hall hub ingested (type hub)" "$HUB" '"type":"hub"' || pass=0 check_rel "Guild Hall hub ownedBy team-devex" "$HUB" ownedBy group:default/team-devex || pass=0 # Live-topology per-repo catalog-info + the aspect's adoption template (vanilla Template kind). diff --git a/yarn.lock b/yarn.lock index 401aeca..187ed14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,6 +19,16 @@ __metadata: languageName: node linkType: hard +"@antfu/install-pkg@npm:^1.1.0": + version: 1.1.0 + resolution: "@antfu/install-pkg@npm:1.1.0" + dependencies: + package-manager-detector: "npm:^1.3.0" + tinyexec: "npm:^1.0.1" + checksum: 10c0/140d5994c76fd3d0e824c88f1ce91b3370e8066a8bc2f5729ae133bf768caa239f7915e29c78f239b7ead253113ace51293e95127fafe2b786b88eb615b3be47 + languageName: node + linkType: hard + "@apidevtools/json-schema-ref-parser@npm:11.7.2": version: 11.7.2 resolution: "@apidevtools/json-schema-ref-parser@npm:11.7.2" @@ -2108,6 +2118,88 @@ __metadata: languageName: node linkType: hard +"@backstage/core-components@npm:^0.18.6": + version: 0.18.12 + resolution: "@backstage/core-components@npm:0.18.12" + dependencies: + "@backstage/config": "npm:^1.3.8" + "@backstage/core-plugin-api": "npm:^1.12.8" + "@backstage/errors": "npm:^1.3.1" + "@backstage/theme": "npm:^0.7.3" + "@backstage/ui": "npm:^0.17.0" + "@backstage/version-bridge": "npm:^1.0.12" + "@dagrejs/dagre": "npm:^1.1.4" + "@date-io/core": "npm:^1.3.13" + "@material-table/core": "npm:^3.1.0" + "@material-ui/core": "npm:^4.12.2" + "@material-ui/icons": "npm:^4.9.1" + "@material-ui/lab": "npm:4.0.0-alpha.61" + "@react-hookz/web": "npm:^24.0.0" + "@testing-library/react": "npm:^16.0.0" + "@types/react-sparklines": "npm:^1.7.0" + ansi-regex: "npm:^6.0.1" + classnames: "npm:^2.2.6" + csstype: "npm:^3.0.2" + d3-selection: "npm:^3.0.0" + d3-shape: "npm:^3.0.0" + d3-zoom: "npm:^3.0.0" + js-yaml: "npm:^4.2.0" + linkify-react: "npm:4.3.2" + linkifyjs: "npm:4.3.2" + lodash: "npm:^4.17.21" + parse5: "npm:^6.0.0" + qs: "npm:^6.15.2" + rc-progress: "npm:3.5.1" + react-full-screen: "npm:^1.1.1" + react-helmet: "npm:6.1.0" + react-hook-form: "npm:^7.12.2" + react-idle-timer: "npm:5.7.2" + react-markdown: "npm:^8.0.0" + react-sparklines: "npm:^1.7.0" + react-syntax-highlighter: "npm:^15.4.5" + react-use: "npm:^17.3.2" + react-virtualized-auto-sizer: "npm:^1.0.11" + react-window: "npm:^1.8.6" + rehype-raw: "npm:^6.0.0" + rehype-sanitize: "npm:^5.0.0" + remark-gfm: "npm:^3.0.1" + zen-observable: "npm:^0.10.0" + zod: "npm:^3.25.76 || ^4.0.0" + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^6.30.2 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/fa94668cf0f8facac7512dc8b2fff70c3dceefcfee569ae2983aa67e72452b35120674f1123a91a965781ae27bd9fa3bdf8af22d88dc6c15cc8220013e500627 + languageName: node + linkType: hard + +"@backstage/core-plugin-api@npm:^1.12.2, @backstage/core-plugin-api@npm:^1.12.8": + version: 1.12.8 + resolution: "@backstage/core-plugin-api@npm:1.12.8" + dependencies: + "@backstage/config": "npm:^1.3.8" + "@backstage/errors": "npm:^1.3.1" + "@backstage/frontend-plugin-api": "npm:^0.17.3" + "@backstage/types": "npm:^1.2.2" + "@backstage/version-bridge": "npm:^1.0.12" + history: "npm:^5.0.0" + zod: "npm:^3.25.76 || ^4.0.0" + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^6.30.2 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/87d99483edca1969a6d56f91b9dccdd1ec544f67f566c0abf15ecfc67984b0322c18128defa841de8fdaaab89be931e8d38a70b14359868056ddd458cbd283bd + languageName: node + linkType: hard + "@backstage/core-plugin-api@npm:^1.12.7": version: 1.12.7 resolution: "@backstage/core-plugin-api@npm:1.12.7" @@ -4017,7 +4109,7 @@ __metadata: languageName: node linkType: hard -"@backstage/theme@npm:^0.7.3": +"@backstage/theme@npm:^0.7.1, @backstage/theme@npm:^0.7.3": version: 0.7.3 resolution: "@backstage/theme@npm:0.7.3" dependencies: @@ -4071,6 +4163,33 @@ __metadata: languageName: node linkType: hard +"@backstage/ui@npm:^0.17.0": + version: 0.17.0 + resolution: "@backstage/ui@npm:0.17.0" + dependencies: + "@backstage/version-bridge": "npm:^1.0.12" + "@braintree/sanitize-url": "npm:^7.1.2" + "@internationalized/date": "npm:^3.12.0" + "@remixicon/react": "npm:>=4.6.0 <4.9.0" + "@tanstack/react-table": "npm:^8.21.3" + clsx: "npm:^2.1.1" + marked: "npm:^15.0.12" + react-aria: "npm:~3.48.0" + react-aria-components: "npm:~1.17.0" + react-stately: "npm:~3.46.0" + use-sync-external-store: "npm:^1.4.0" + peerDependencies: + "@types/react": ^18.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 + react-router-dom: ^6.30.2 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/0e36fa81bfc6b872ef69e369e00fae6a020232e49e6997bb81ba027f783d6a8a539ecc761ed93cf5b80c2810ee71a20ef27e475f2a33b8343333c699348ad68d + languageName: node + linkType: hard + "@backstage/version-bridge@npm:^1.0.12": version: 1.0.12 resolution: "@backstage/version-bridge@npm:1.0.12" @@ -4132,6 +4251,13 @@ __metadata: languageName: node linkType: hard +"@chevrotain/types@npm:~11.1.2": + version: 11.1.2 + resolution: "@chevrotain/types@npm:11.1.2" + checksum: 10c0/c0c4679a3d407df34e18d5adfa7ac599b4a2bfddbf68da6e43678b9b3e16ab911de7766b37b9fc466261c3dead3db1b620e2e344f800fa9f0f381720475eda8f + languageName: node + linkType: hard + "@codemirror/autocomplete@npm:^6.0.0": version: 6.20.3 resolution: "@codemirror/autocomplete@npm:6.20.3" @@ -5166,6 +5292,24 @@ __metadata: languageName: node linkType: hard +"@iconify/types@npm:^2.0.0": + version: 2.0.0 + resolution: "@iconify/types@npm:2.0.0" + checksum: 10c0/65a3be43500c7ccacf360e136d00e1717f050b7b91da644e94370256ac66f582d59212bdb30d00788aab4fc078262e91c95b805d1808d654b72f6d2072a7e4b2 + languageName: node + linkType: hard + +"@iconify/utils@npm:^3.0.2": + version: 3.1.4 + resolution: "@iconify/utils@npm:3.1.4" + dependencies: + "@antfu/install-pkg": "npm:^1.1.0" + "@iconify/types": "npm:^2.0.0" + import-meta-resolve: "npm:^4.2.0" + checksum: 10c0/2176311415d5853e0e19056a833014324d0a98989936945fbcc4fb4b0ae92178f6ed13c9b4c8e1200191991b78af421b7dd49cc03b474c7a824696d73033e1c1 + languageName: node + linkType: hard + "@inquirer/external-editor@npm:^1.0.0": version: 1.0.3 resolution: "@inquirer/external-editor@npm:1.0.3" @@ -6407,6 +6551,15 @@ __metadata: languageName: node linkType: hard +"@mermaid-js/parser@npm:^1.2.0": + version: 1.2.0 + resolution: "@mermaid-js/parser@npm:1.2.0" + dependencies: + "@chevrotain/types": "npm:~11.1.2" + checksum: 10c0/907d41167b23160c88f292b0dd79162d2543445ecf1d784ed09747467705666669f818e3ab91e1182da2127720fb40cb707e6fd56e8a445020fd3e7b8b16f013 + languageName: node + linkType: hard + "@microsoft/fetch-event-source@npm:^2.0.1": version: 2.0.1 resolution: "@microsoft/fetch-event-source@npm:2.0.1" @@ -9040,6 +9193,26 @@ __metadata: languageName: node linkType: hard +"@siliconsaga/plugin-gildi@npm:^0.1.0, @siliconsaga/plugin-gildi@workspace:plugins/gildi": + version: 0.0.0-use.local + resolution: "@siliconsaga/plugin-gildi@workspace:plugins/gildi" + dependencies: + "@backstage/cli": "npm:^0.36.3" + "@backstage/core-components": "npm:^0.18.11" + "@backstage/frontend-plugin-api": "npm:^0.17.2" + "@backstage/frontend-test-utils": "npm:^0.6.1" + "@backstage/plugin-catalog-react": "npm:^3.1.0" + "@backstage/ui": "npm:^0.16.0" + "@material-ui/icons": "npm:^4.9.1" + "@testing-library/jest-dom": "npm:^6.0.0" + "@testing-library/react": "npm:^14.0.0" + react-router-dom: "npm:^6.30.2" + peerDependencies: + react: ^17 || ^18 + react-dom: ^17 || ^18 + languageName: unknown + linkType: soft + "@sinclair/typebox@npm:^0.27.8": version: 0.27.10 resolution: "@sinclair/typebox@npm:0.27.10" @@ -10758,6 +10931,278 @@ __metadata: languageName: node linkType: hard +"@types/d3-array@npm:*": + version: 3.2.2 + resolution: "@types/d3-array@npm:3.2.2" + checksum: 10c0/6137cb97302f8a4f18ca22c0560c585cfcb823f276b23d89f2c0c005d72697ec13bca671c08e68b4b0cabd622e3f0e91782ee221580d6774074050be96dd7028 + languageName: node + linkType: hard + +"@types/d3-axis@npm:*": + version: 3.0.6 + resolution: "@types/d3-axis@npm:3.0.6" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/d756d42360261f44d8eefd0950c5bb0a4f67a46dd92069da3f723ac36a1e8cb2b9ce6347d836ef19d5b8aef725dbcf8fdbbd6cfbff676ca4b0642df2f78b599a + languageName: node + linkType: hard + +"@types/d3-brush@npm:*": + version: 3.0.6 + resolution: "@types/d3-brush@npm:3.0.6" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/fd6e2ac7657a354f269f6b9c58451ffae9d01b89ccb1eb6367fd36d635d2f1990967215ab498e0c0679ff269429c57fad6a2958b68f4d45bc9f81d81672edc01 + languageName: node + linkType: hard + +"@types/d3-chord@npm:*": + version: 3.0.6 + resolution: "@types/d3-chord@npm:3.0.6" + checksum: 10c0/c5a25eb5389db01e63faec0c5c2ec7cc41c494e9b3201630b494c4e862a60f1aa83fabbc33a829e7e1403941e3c30d206c741559b14406ac2a4239cfdf4b4c17 + languageName: node + linkType: hard + +"@types/d3-color@npm:*": + version: 3.1.3 + resolution: "@types/d3-color@npm:3.1.3" + checksum: 10c0/65eb0487de606eb5ad81735a9a5b3142d30bc5ea801ed9b14b77cb14c9b909f718c059f13af341264ee189acf171508053342142bdf99338667cea26a2d8d6ae + languageName: node + linkType: hard + +"@types/d3-contour@npm:*": + version: 3.0.6 + resolution: "@types/d3-contour@npm:3.0.6" + dependencies: + "@types/d3-array": "npm:*" + "@types/geojson": "npm:*" + checksum: 10c0/e7d83e94719af4576ceb5ac7f277c5806f83ba6c3631744ae391cffc3641f09dfa279470b83053cd0b2acd6784e8749c71141d05bdffa63ca58ffb5b31a0f27c + languageName: node + linkType: hard + +"@types/d3-delaunay@npm:*": + version: 6.0.4 + resolution: "@types/d3-delaunay@npm:6.0.4" + checksum: 10c0/d154a8864f08c4ea23ecb9bdabcef1c406a25baa8895f0cb08a0ed2799de0d360e597552532ce7086ff0cdffa8f3563f9109d18f0191459d32bb620a36939123 + languageName: node + linkType: hard + +"@types/d3-dispatch@npm:*": + version: 3.0.7 + resolution: "@types/d3-dispatch@npm:3.0.7" + checksum: 10c0/38c6605ebf0bf0099dfb70eafe0dd4ae8213368b40b8f930b72a909ff2e7259d2bd8a54d100bb5a44eb4b36f4f2a62dcb37f8be59613ca6b507c7a2f910b3145 + languageName: node + linkType: hard + +"@types/d3-drag@npm:*": + version: 3.0.7 + resolution: "@types/d3-drag@npm:3.0.7" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/65e29fa32a87c72d26c44b5e2df3bf15af21cd128386bcc05bcacca255927c0397d0cd7e6062aed5f0abd623490544a9d061c195f5ed9f018fe0b698d99c079d + languageName: node + linkType: hard + +"@types/d3-dsv@npm:*": + version: 3.0.7 + resolution: "@types/d3-dsv@npm:3.0.7" + checksum: 10c0/c0f01da862465594c8a28278b51c850af3b4239cc22b14fd1a19d7a98f93d94efa477bf59d8071beb285dca45bf614630811451e18e7c52add3a0abfee0a1871 + languageName: node + linkType: hard + +"@types/d3-ease@npm:*": + version: 3.0.2 + resolution: "@types/d3-ease@npm:3.0.2" + checksum: 10c0/aff5a1e572a937ee9bff6465225d7ba27d5e0c976bd9eacdac2e6f10700a7cb0c9ea2597aff6b43a6ed850a3210030870238894a77ec73e309b4a9d0333f099c + languageName: node + linkType: hard + +"@types/d3-fetch@npm:*": + version: 3.0.7 + resolution: "@types/d3-fetch@npm:3.0.7" + dependencies: + "@types/d3-dsv": "npm:*" + checksum: 10c0/3d147efa52a26da1a5d40d4d73e6cebaaa964463c378068062999b93ea3731b27cc429104c21ecbba98c6090e58ef13429db6399238c5e3500162fb3015697a0 + languageName: node + linkType: hard + +"@types/d3-force@npm:*": + version: 3.0.10 + resolution: "@types/d3-force@npm:3.0.10" + checksum: 10c0/c82b459079a106b50e346c9b79b141f599f2fc4f598985a5211e72c7a2e20d35bd5dc6e91f306b323c8bfa325c02c629b1645f5243f1c6a55bd51bc85cccfa92 + languageName: node + linkType: hard + +"@types/d3-format@npm:*": + version: 3.0.4 + resolution: "@types/d3-format@npm:3.0.4" + checksum: 10c0/3ac1600bf9061a59a228998f7cd3f29e85cbf522997671ba18d4d84d10a2a1aff4f95aceb143fa9960501c3ec351e113fc75884e6a504ace44dc1744083035ee + languageName: node + linkType: hard + +"@types/d3-geo@npm:*": + version: 3.1.0 + resolution: "@types/d3-geo@npm:3.1.0" + dependencies: + "@types/geojson": "npm:*" + checksum: 10c0/3745a93439038bb5b0b38facf435f7079812921d46406f5d38deaee59e90084ff742443c7ea0a8446df81a0d81eaf622fe7068cf4117a544bd4aa3b2dc182f88 + languageName: node + linkType: hard + +"@types/d3-hierarchy@npm:*": + version: 3.1.7 + resolution: "@types/d3-hierarchy@npm:3.1.7" + checksum: 10c0/873711737d6b8e7b6f1dda0bcd21294a48f75024909ae510c5d2c21fad2e72032e0958def4d9f68319d3aaac298ad09c49807f8bfc87a145a82693b5208613c7 + languageName: node + linkType: hard + +"@types/d3-interpolate@npm:*": + version: 3.0.4 + resolution: "@types/d3-interpolate@npm:3.0.4" + dependencies: + "@types/d3-color": "npm:*" + checksum: 10c0/066ebb8da570b518dd332df6b12ae3b1eaa0a7f4f0c702e3c57f812cf529cc3500ec2aac8dc094f31897790346c6b1ebd8cd7a077176727f4860c2b181a65ca4 + languageName: node + linkType: hard + +"@types/d3-path@npm:*": + version: 3.1.1 + resolution: "@types/d3-path@npm:3.1.1" + checksum: 10c0/2c36eb31ebaf2ce4712e793fd88087117976f7c4ed69cc2431825f999c8c77cca5cea286f3326432b770739ac6ccd5d04d851eb65e7a4dbcc10c982b49ad2c02 + languageName: node + linkType: hard + +"@types/d3-polygon@npm:*": + version: 3.0.2 + resolution: "@types/d3-polygon@npm:3.0.2" + checksum: 10c0/f46307bb32b6c2aef8c7624500e0f9b518de8f227ccc10170b869dc43e4c542560f6c8d62e9f087fac45e198d6e4b623e579c0422e34c85baf56717456d3f439 + languageName: node + linkType: hard + +"@types/d3-quadtree@npm:*": + version: 3.0.6 + resolution: "@types/d3-quadtree@npm:3.0.6" + checksum: 10c0/7eaa0a4d404adc856971c9285e1c4ab17e9135ea669d847d6db7e0066126a28ac751864e7ce99c65d526e130f56754a2e437a1617877098b3bdcc3ef23a23616 + languageName: node + linkType: hard + +"@types/d3-random@npm:*": + version: 3.0.4 + resolution: "@types/d3-random@npm:3.0.4" + checksum: 10c0/7661fe7c5071ea8a35b31a5532816a693b5e887d7635954c1ee214ac3dba727061a46b58401f862e404d1c0122c62810317ddde5bcec89f13106cb022b9d3f09 + languageName: node + linkType: hard + +"@types/d3-scale-chromatic@npm:*": + version: 3.1.0 + resolution: "@types/d3-scale-chromatic@npm:3.1.0" + checksum: 10c0/93c564e02d2e97a048e18fe8054e4a935335da6ab75a56c3df197beaa87e69122eef0dfbeb7794d4a444a00e52e3123514ee27cec084bd21f6425b7037828cc2 + languageName: node + linkType: hard + +"@types/d3-scale@npm:*": + version: 4.0.9 + resolution: "@types/d3-scale@npm:4.0.9" + dependencies: + "@types/d3-time": "npm:*" + checksum: 10c0/4ac44233c05cd50b65b33ecb35d99fdf07566bcdbc55bc1306b2f27d1c5134d8c560d356f2c8e76b096e9125ffb8d26d95f78d56e210d1c542cb255bdf31d6c8 + languageName: node + linkType: hard + +"@types/d3-selection@npm:*": + version: 3.0.11 + resolution: "@types/d3-selection@npm:3.0.11" + checksum: 10c0/0c512956c7503ff5def4bb32e0c568cc757b9a2cc400a104fc0f4cfe5e56d83ebde2a97821b6f2cb26a7148079d3b86a2f28e11d68324ed311cf35c2ed980d1d + languageName: node + linkType: hard + +"@types/d3-shape@npm:*": + version: 3.1.8 + resolution: "@types/d3-shape@npm:3.1.8" + dependencies: + "@types/d3-path": "npm:*" + checksum: 10c0/49ec2172b9eb66fc1d036e2a23966216bb972e9af51ddbed134df24bd71aedf207bb1ef81903a119eb4e1f5e927cf44beacaf64c9af86474e5548594b102b574 + languageName: node + linkType: hard + +"@types/d3-time-format@npm:*": + version: 4.0.3 + resolution: "@types/d3-time-format@npm:4.0.3" + checksum: 10c0/9ef5e8e2b96b94799b821eed5d61a3d432c7903247966d8ad951b8ce5797fe46554b425cb7888fa5bf604b4663c369d7628c0328ffe80892156671c58d1a7f90 + languageName: node + linkType: hard + +"@types/d3-time@npm:*": + version: 3.0.4 + resolution: "@types/d3-time@npm:3.0.4" + checksum: 10c0/6d9e2255d63f7a313a543113920c612e957d70da4fb0890931da6c2459010291b8b1f95e149a538500c1c99e7e6c89ffcce5554dd29a31ff134a38ea94b6d174 + languageName: node + linkType: hard + +"@types/d3-timer@npm:*": + version: 3.0.2 + resolution: "@types/d3-timer@npm:3.0.2" + checksum: 10c0/c644dd9571fcc62b1aa12c03bcad40571553020feeb5811f1d8a937ac1e65b8a04b759b4873aef610e28b8714ac71c9885a4d6c127a048d95118f7e5b506d9e1 + languageName: node + linkType: hard + +"@types/d3-transition@npm:*": + version: 3.0.9 + resolution: "@types/d3-transition@npm:3.0.9" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/4f68b9df7ac745b3491216c54203cbbfa0f117ae4c60e2609cdef2db963582152035407fdff995b10ee383bae2f05b7743493f48e1b8e46df54faa836a8fb7b5 + languageName: node + linkType: hard + +"@types/d3-zoom@npm:*": + version: 3.0.8 + resolution: "@types/d3-zoom@npm:3.0.8" + dependencies: + "@types/d3-interpolate": "npm:*" + "@types/d3-selection": "npm:*" + checksum: 10c0/1dbdbcafddcae12efb5beb6948546963f29599e18bc7f2a91fb69cc617c2299a65354f2d47e282dfb86fec0968406cd4fb7f76ba2d2fb67baa8e8d146eb4a547 + languageName: node + linkType: hard + +"@types/d3@npm:^7.4.3": + version: 7.4.3 + resolution: "@types/d3@npm:7.4.3" + dependencies: + "@types/d3-array": "npm:*" + "@types/d3-axis": "npm:*" + "@types/d3-brush": "npm:*" + "@types/d3-chord": "npm:*" + "@types/d3-color": "npm:*" + "@types/d3-contour": "npm:*" + "@types/d3-delaunay": "npm:*" + "@types/d3-dispatch": "npm:*" + "@types/d3-drag": "npm:*" + "@types/d3-dsv": "npm:*" + "@types/d3-ease": "npm:*" + "@types/d3-fetch": "npm:*" + "@types/d3-force": "npm:*" + "@types/d3-format": "npm:*" + "@types/d3-geo": "npm:*" + "@types/d3-hierarchy": "npm:*" + "@types/d3-interpolate": "npm:*" + "@types/d3-path": "npm:*" + "@types/d3-polygon": "npm:*" + "@types/d3-quadtree": "npm:*" + "@types/d3-random": "npm:*" + "@types/d3-scale": "npm:*" + "@types/d3-scale-chromatic": "npm:*" + "@types/d3-selection": "npm:*" + "@types/d3-shape": "npm:*" + "@types/d3-time": "npm:*" + "@types/d3-time-format": "npm:*" + "@types/d3-timer": "npm:*" + "@types/d3-transition": "npm:*" + "@types/d3-zoom": "npm:*" + checksum: 10c0/a9c6d65b13ef3b42c87f2a89ea63a6d5640221869f97d0657b0cb2f1dac96a0f164bf5605643c0794e0de3aa2bf05df198519aaf15d24ca135eb0e8bd8a9d879 + languageName: node + linkType: hard + "@types/debug@npm:^4.0.0": version: 4.1.13 resolution: "@types/debug@npm:4.1.13" @@ -10860,6 +11305,13 @@ __metadata: languageName: node linkType: hard +"@types/geojson@npm:*": + version: 7946.0.16 + resolution: "@types/geojson@npm:7946.0.16" + checksum: 10c0/1ff24a288bd5860b766b073ead337d31d73bdc715e5b50a2cee5cb0af57a1ed02cc04ef295f5fa68dc40fe3e4f104dd31282b2b818a5ba3231bc1001ba084e3c + languageName: node + linkType: hard + "@types/hast@npm:^2.0.0": version: 2.3.10 resolution: "@types/hast@npm:2.3.10" @@ -11880,6 +12332,21 @@ __metadata: languageName: node linkType: hard +"@upsetjs/venn.js@npm:^2.0.0": + version: 2.0.0 + resolution: "@upsetjs/venn.js@npm:2.0.0" + dependencies: + d3-selection: "npm:^3.0.0" + d3-transition: "npm:^3.0.1" + dependenciesMeta: + d3-selection: + optional: true + d3-transition: + optional: true + checksum: 10c0/b12014d94708ab4df7f5a4b6205c6f23ff235cca2ffe91df3314862b109b826e52f9020c2a2f7527d3712d21c578d6db9cdb60ce46a528739cc18e58d111f724 + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/ast@npm:1.14.1" @@ -12512,11 +12979,13 @@ __metadata: "@material-ui/core": "npm:^4.12.2" "@material-ui/icons": "npm:^4.9.1" "@playwright/test": "npm:^1.32.3" + "@siliconsaga/plugin-gildi": "npm:^0.1.0" "@testing-library/dom": "npm:^9.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^14.0.0" "@testing-library/user-event": "npm:^14.0.0" "@types/react-dom": "npm:*" + backstage-plugin-techdocs-addon-mermaid: "npm:^0.26.0" cross-env: "npm:^7.0.0" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" @@ -13152,6 +13621,35 @@ __metadata: languageName: node linkType: hard +"backstage-plugin-techdocs-addon-mermaid@npm:^0.26.0": + version: 0.26.0 + resolution: "backstage-plugin-techdocs-addon-mermaid@npm:0.26.0" + dependencies: + "@backstage/core-components": "npm:^0.18.6" + "@backstage/core-plugin-api": "npm:^1.12.2" + "@backstage/frontend-plugin-api": "npm:^0.13.4" + "@backstage/plugin-techdocs-react": "npm:^1.3.7" + "@backstage/theme": "npm:^0.7.1" + "@material-ui/core": "npm:^4.12.2" + "@material-ui/icons": "npm:^4.11.3" + "@material-ui/lab": "npm:4.0.0-alpha.61" + d3: "npm:^7.9.0" + d3-selection: "npm:^3.0.0" + d3-zoom: "npm:^3.0.0" + mermaid: "npm:^11.6.0" + react-use: "npm:^17.2.4" + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^6.3.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/29faf75cb54f2a34c13c3909653427ec9e91111b554e708defacb8e035dc7142a822c7112111eec494345914d37c5d8164d614b80253f5688d1f322429bf14a1 + languageName: node + linkType: hard + "bail@npm:^2.0.0": version: 2.0.2 resolution: "bail@npm:2.0.2" @@ -14458,6 +14956,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:7, commander@npm:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a + languageName: node + linkType: hard + "commander@npm:^10.0.0": version: 10.0.1 resolution: "commander@npm:10.0.1" @@ -14481,15 +14986,8 @@ __metadata: "commander@npm:^5.1.0": version: 5.1.0 - resolution: "commander@npm:5.1.0" - checksum: 10c0/da9d71dbe4ce039faf1fe9eac3771dca8c11d66963341f62602f7b66e36d2a3f8883407af4f9a37b1db1a55c59c0c1325f186425764c2e963dc1d67aec2a4b6d - languageName: node - linkType: hard - -"commander@npm:^7.2.0": - version: 7.2.0 - resolution: "commander@npm:7.2.0" - checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a + resolution: "commander@npm:5.1.0" + checksum: 10c0/da9d71dbe4ce039faf1fe9eac3771dca8c11d66963341f62602f7b66e36d2a3f8883407af4f9a37b1db1a55c59c0c1325f186425764c2e963dc1d67aec2a4b6d languageName: node linkType: hard @@ -14788,6 +15286,24 @@ __metadata: languageName: node linkType: hard +"cose-base@npm:^1.0.0": + version: 1.0.3 + resolution: "cose-base@npm:1.0.3" + dependencies: + layout-base: "npm:^1.0.0" + checksum: 10c0/a6e400b1d101393d6af0967c1353355777c1106c40417c5acaef6ca8bdda41e2fc9398f466d6c85be30290943ad631f2590569f67b3fd5368a0d8318946bd24f + languageName: node + linkType: hard + +"cose-base@npm:^2.2.0": + version: 2.2.0 + resolution: "cose-base@npm:2.2.0" + dependencies: + layout-base: "npm:^2.0.0" + checksum: 10c0/14b9f8100ac322a00777ffb1daeb3321af368bbc9cabe3103943361273baee2003202ffe38e4ab770960b600214224e9c196195a78d589521540aa694df7cdec + languageName: node + linkType: hard + "cosmiconfig@npm:^6.0.0": version: 6.0.0 resolution: "cosmiconfig@npm:6.0.0" @@ -15249,21 +15765,115 @@ __metadata: languageName: node linkType: hard -"d3-color@npm:1 - 3": +"cytoscape-cose-bilkent@npm:^4.1.0": + version: 4.1.0 + resolution: "cytoscape-cose-bilkent@npm:4.1.0" + dependencies: + cose-base: "npm:^1.0.0" + peerDependencies: + cytoscape: ^3.2.0 + checksum: 10c0/5e2480ddba9da1a68e700ed2c674cbfd51e9efdbd55788f1971a68de4eb30708e3b3a5e808bf5628f7a258680406bbe6586d87a9133e02a9bdc1ab1a92f512f2 + languageName: node + linkType: hard + +"cytoscape-fcose@npm:^2.2.0": + version: 2.2.0 + resolution: "cytoscape-fcose@npm:2.2.0" + dependencies: + cose-base: "npm:^2.2.0" + peerDependencies: + cytoscape: ^3.2.0 + checksum: 10c0/ce472c9f85b9057e75c5685396f8e1f2468895e71b184913e05ad56dcf3092618fe59a1054f29cb0995051ba8ebe566ad0dd49a58d62845145624bd60cd44917 + languageName: node + linkType: hard + +"cytoscape@npm:^3.33.3": + version: 3.34.0 + resolution: "cytoscape@npm:3.34.0" + checksum: 10c0/cb17b3dcacb9492f058cff653debf7b5a713e7532a9866cc72ae79d207757e8a9b68430874fe986f2a6404a8161b4fb5c1a2f1ca9ac5b1a21e316f57ed9d1243 + languageName: node + linkType: hard + +"d3-array@npm:1 - 2": + version: 2.12.1 + resolution: "d3-array@npm:2.12.1" + dependencies: + internmap: "npm:^1.0.0" + checksum: 10c0/7eca10427a9f113a4ca6a0f7301127cab26043fd5e362631ef5a0edd1c4b2dd70c56ed317566700c31e4a6d88b55f3951aaba192291817f243b730cb2352882e + languageName: node + linkType: hard + +"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.2.0": + version: 3.2.4 + resolution: "d3-array@npm:3.2.4" + dependencies: + internmap: "npm:1 - 2" + checksum: 10c0/08b95e91130f98c1375db0e0af718f4371ccacef7d5d257727fe74f79a24383e79aba280b9ffae655483ffbbad4fd1dec4ade0119d88c4749f388641c8bf8c50 + languageName: node + linkType: hard + +"d3-axis@npm:3": + version: 3.0.0 + resolution: "d3-axis@npm:3.0.0" + checksum: 10c0/a271e70ba1966daa5aaf6a7f959ceca3e12997b43297e757c7b945db2e1ead3c6ee226f2abcfa22abbd4e2e28bd2b71a0911794c4e5b911bbba271328a582c78 + languageName: node + linkType: hard + +"d3-brush@npm:3": + version: 3.0.0 + resolution: "d3-brush@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-drag: "npm:2 - 3" + d3-interpolate: "npm:1 - 3" + d3-selection: "npm:3" + d3-transition: "npm:3" + checksum: 10c0/07baf00334c576da2f68a91fc0da5732c3a5fa19bd3d7aed7fd24d1d674a773f71a93e9687c154176f7246946194d77c48c2d8fed757f5dcb1a4740067ec50a8 + languageName: node + linkType: hard + +"d3-chord@npm:3": + version: 3.0.1 + resolution: "d3-chord@npm:3.0.1" + dependencies: + d3-path: "npm:1 - 3" + checksum: 10c0/baa6013914af3f4fe1521f0d16de31a38eb8a71d08ff1dec4741f6f45a828661e5cd3935e39bd14e3032bdc78206c283ca37411da21d46ec3cfc520be6e7a7ce + languageName: node + linkType: hard + +"d3-color@npm:1 - 3, d3-color@npm:3": version: 3.1.0 resolution: "d3-color@npm:3.1.0" checksum: 10c0/a4e20e1115fa696fce041fbe13fbc80dc4c19150fa72027a7c128ade980bc0eeeba4bcf28c9e21f0bce0e0dbfe7ca5869ef67746541dcfda053e4802ad19783c languageName: node linkType: hard -"d3-dispatch@npm:1 - 3": +"d3-contour@npm:4": + version: 4.0.2 + resolution: "d3-contour@npm:4.0.2" + dependencies: + d3-array: "npm:^3.2.0" + checksum: 10c0/98bc5fbed6009e08707434a952076f39f1cd6ed8b9288253cc3e6a3286e4e80c63c62d84954b20e64bf6e4ededcc69add54d3db25e990784a59c04edd3449032 + languageName: node + linkType: hard + +"d3-delaunay@npm:6": + version: 6.0.4 + resolution: "d3-delaunay@npm:6.0.4" + dependencies: + delaunator: "npm:5" + checksum: 10c0/57c3aecd2525664b07c4c292aa11cf49b2752c0cf3f5257f752999399fe3c592de2d418644d79df1f255471eec8057a9cc0c3062ed7128cb3348c45f69597754 + languageName: node + linkType: hard + +"d3-dispatch@npm:1 - 3, d3-dispatch@npm:3": version: 3.0.1 resolution: "d3-dispatch@npm:3.0.1" checksum: 10c0/6eca77008ce2dc33380e45d4410c67d150941df7ab45b91d116dbe6d0a3092c0f6ac184dd4602c796dc9e790222bad3ff7142025f5fd22694efe088d1d941753 languageName: node linkType: hard -"d3-drag@npm:2 - 3": +"d3-drag@npm:2 - 3, d3-drag@npm:3": version: 3.0.0 resolution: "d3-drag@npm:3.0.0" dependencies: @@ -15273,14 +15883,78 @@ __metadata: languageName: node linkType: hard -"d3-ease@npm:1 - 3": +"d3-dsv@npm:1 - 3, d3-dsv@npm:3": + version: 3.0.1 + resolution: "d3-dsv@npm:3.0.1" + dependencies: + commander: "npm:7" + iconv-lite: "npm:0.6" + rw: "npm:1" + bin: + csv2json: bin/dsv2json.js + csv2tsv: bin/dsv2dsv.js + dsv2dsv: bin/dsv2dsv.js + dsv2json: bin/dsv2json.js + json2csv: bin/json2dsv.js + json2dsv: bin/json2dsv.js + json2tsv: bin/json2dsv.js + tsv2csv: bin/dsv2dsv.js + tsv2json: bin/dsv2json.js + checksum: 10c0/10e6af9e331950ed258f34ab49ac1b7060128ef81dcf32afc790bd1f7e8c3cc2aac7f5f875250a83f21f39bb5925fbd0872bb209f8aca32b3b77d32bab8a65ab + languageName: node + linkType: hard + +"d3-ease@npm:1 - 3, d3-ease@npm:3": version: 3.0.1 resolution: "d3-ease@npm:3.0.1" checksum: 10c0/fec8ef826c0cc35cda3092c6841e07672868b1839fcaf556e19266a3a37e6bc7977d8298c0fcb9885e7799bfdcef7db1baaba9cd4dcf4bc5e952cf78574a88b0 languageName: node linkType: hard -"d3-interpolate@npm:1 - 3": +"d3-fetch@npm:3": + version: 3.0.1 + resolution: "d3-fetch@npm:3.0.1" + dependencies: + d3-dsv: "npm:1 - 3" + checksum: 10c0/4f467a79bf290395ac0cbb5f7562483f6a18668adc4c8eb84c9d3eff048b6f6d3b6f55079ba1ebf1908dabe000c941d46be447f8d78453b2dad5fb59fb6aa93b + languageName: node + linkType: hard + +"d3-force@npm:3": + version: 3.0.0 + resolution: "d3-force@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-quadtree: "npm:1 - 3" + d3-timer: "npm:1 - 3" + checksum: 10c0/220a16a1a1ac62ba56df61028896e4b52be89c81040d20229c876efc8852191482c233f8a52bb5a4e0875c321b8e5cb6413ef3dfa4d8fe79eeb7d52c587f52cf + languageName: node + linkType: hard + +"d3-format@npm:1 - 3, d3-format@npm:3": + version: 3.1.2 + resolution: "d3-format@npm:3.1.2" + checksum: 10c0/0de452ae07585238e7f01607a7e0066665c34609652188b6ac7dc9f424f69465a425e07d16d79bd0e5955202ac7f241c66d0c76f68a79fc6f4857c94cf420652 + languageName: node + linkType: hard + +"d3-geo@npm:3": + version: 3.1.1 + resolution: "d3-geo@npm:3.1.1" + dependencies: + d3-array: "npm:2.5.0 - 3" + checksum: 10c0/d32270dd2dc8ac3ea63e8805d63239c4c8ec6c0d339d73b5e5a30a87f8f54db22a78fb434369799465eae169503b25f9a107c642c8a16c32a3285bc0e6d8e8c1 + languageName: node + linkType: hard + +"d3-hierarchy@npm:3": + version: 3.1.2 + resolution: "d3-hierarchy@npm:3.1.2" + checksum: 10c0/6dcdb480539644aa7fc0d72dfc7b03f99dfbcdf02714044e8c708577e0d5981deb9d3e99bbbb2d26422b55bcc342ac89a0fa2ea6c9d7302e2fc0951dd96f89cf + languageName: node + linkType: hard + +"d3-interpolate@npm:1 - 3, d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:3": version: 3.0.1 resolution: "d3-interpolate@npm:3.0.1" dependencies: @@ -15289,13 +15963,74 @@ __metadata: languageName: node linkType: hard -"d3-path@npm:^3.1.0": +"d3-path@npm:1": + version: 1.0.9 + resolution: "d3-path@npm:1.0.9" + checksum: 10c0/e35e84df5abc18091f585725b8235e1fa97efc287571585427d3a3597301e6c506dea56b11dfb3c06ca5858b3eb7f02c1bf4f6a716aa9eade01c41b92d497eb5 + languageName: node + linkType: hard + +"d3-path@npm:1 - 3, d3-path@npm:3, d3-path@npm:^3.1.0": version: 3.1.0 resolution: "d3-path@npm:3.1.0" checksum: 10c0/dc1d58ec87fa8319bd240cf7689995111a124b141428354e9637aa83059eb12e681f77187e0ada5dedfce346f7e3d1f903467ceb41b379bfd01cd8e31721f5da languageName: node linkType: hard +"d3-polygon@npm:3": + version: 3.0.1 + resolution: "d3-polygon@npm:3.0.1" + checksum: 10c0/e236aa7f33efa9a4072907af7dc119f85b150a0716759d4fe5f12f62573018264a6cbde8617fbfa6944a7ae48c1c0c8d3f39ae72e11f66dd471e9b5e668385df + languageName: node + linkType: hard + +"d3-quadtree@npm:1 - 3, d3-quadtree@npm:3": + version: 3.0.1 + resolution: "d3-quadtree@npm:3.0.1" + checksum: 10c0/18302d2548bfecaef788152397edec95a76400fd97d9d7f42a089ceb68d910f685c96579d74e3712d57477ed042b056881b47cd836a521de683c66f47ce89090 + languageName: node + linkType: hard + +"d3-random@npm:3": + version: 3.0.1 + resolution: "d3-random@npm:3.0.1" + checksum: 10c0/987a1a1bcbf26e6cf01fd89d5a265b463b2cea93560fc17d9b1c45e8ed6ff2db5924601bcceb808de24c94133f000039eb7fa1c469a7a844ccbf1170cbb25b41 + languageName: node + linkType: hard + +"d3-sankey@npm:^0.12.3": + version: 0.12.3 + resolution: "d3-sankey@npm:0.12.3" + dependencies: + d3-array: "npm:1 - 2" + d3-shape: "npm:^1.2.0" + checksum: 10c0/261debb01a13269f6fc53b9ebaef174a015d5ad646242c23995bf514498829ab8b8f920a7873724a7494288b46bea3ce7ebc5a920b745bc8ae4caa5885cf5204 + languageName: node + linkType: hard + +"d3-scale-chromatic@npm:3": + version: 3.1.0 + resolution: "d3-scale-chromatic@npm:3.1.0" + dependencies: + d3-color: "npm:1 - 3" + d3-interpolate: "npm:1 - 3" + checksum: 10c0/9a3f4671ab0b971f4a411b42180d7cf92bfe8e8584e637ce7e698d705e18d6d38efbd20ec64f60cc0dfe966c20d40fc172565bc28aaa2990c0a006360eed91af + languageName: node + linkType: hard + +"d3-scale@npm:4": + version: 4.0.2 + resolution: "d3-scale@npm:4.0.2" + dependencies: + d3-array: "npm:2.10.0 - 3" + d3-format: "npm:1 - 3" + d3-interpolate: "npm:1.2.0 - 3" + d3-time: "npm:2.1.1 - 3" + d3-time-format: "npm:2 - 4" + checksum: 10c0/65d9ad8c2641aec30ed5673a7410feb187a224d6ca8d1a520d68a7d6eac9d04caedbff4713d1e8545be33eb7fec5739983a7ab1d22d4e5ad35368c6729d362f1 + languageName: node + linkType: hard + "d3-selection@npm:2 - 3, d3-selection@npm:3, d3-selection@npm:^3.0.0": version: 3.0.0 resolution: "d3-selection@npm:3.0.0" @@ -15303,7 +16038,7 @@ __metadata: languageName: node linkType: hard -"d3-shape@npm:^3.0.0": +"d3-shape@npm:3, d3-shape@npm:^3.0.0": version: 3.2.0 resolution: "d3-shape@npm:3.2.0" dependencies: @@ -15312,14 +16047,41 @@ __metadata: languageName: node linkType: hard -"d3-timer@npm:1 - 3": +"d3-shape@npm:^1.2.0": + version: 1.3.7 + resolution: "d3-shape@npm:1.3.7" + dependencies: + d3-path: "npm:1" + checksum: 10c0/548057ce59959815decb449f15632b08e2a1bdce208f9a37b5f98ec7629dda986c2356bc7582308405ce68aedae7d47b324df41507404df42afaf352907577ae + languageName: node + linkType: hard + +"d3-time-format@npm:2 - 4, d3-time-format@npm:4": + version: 4.1.0 + resolution: "d3-time-format@npm:4.1.0" + dependencies: + d3-time: "npm:1 - 3" + checksum: 10c0/735e00fb25a7fd5d418fac350018713ae394eefddb0d745fab12bbff0517f9cdb5f807c7bbe87bb6eeb06249662f8ea84fec075f7d0cd68609735b2ceb29d206 + languageName: node + linkType: hard + +"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:3": + version: 3.1.0 + resolution: "d3-time@npm:3.1.0" + dependencies: + d3-array: "npm:2 - 3" + checksum: 10c0/a984f77e1aaeaa182679b46fbf57eceb6ebdb5f67d7578d6f68ef933f8eeb63737c0949991618a8d29472dbf43736c7d7f17c452b2770f8c1271191cba724ca1 + languageName: node + linkType: hard + +"d3-timer@npm:1 - 3, d3-timer@npm:3": version: 3.0.1 resolution: "d3-timer@npm:3.0.1" checksum: 10c0/d4c63cb4bb5461d7038aac561b097cd1c5673969b27cbdd0e87fa48d9300a538b9e6f39b4a7f0e3592ef4f963d858c8a9f0e92754db73116770856f2fc04561a languageName: node linkType: hard -"d3-transition@npm:2 - 3": +"d3-transition@npm:2 - 3, d3-transition@npm:3, d3-transition@npm:^3.0.1": version: 3.0.1 resolution: "d3-transition@npm:3.0.1" dependencies: @@ -15334,7 +16096,7 @@ __metadata: languageName: node linkType: hard -"d3-zoom@npm:^3.0.0": +"d3-zoom@npm:3, d3-zoom@npm:^3.0.0": version: 3.0.0 resolution: "d3-zoom@npm:3.0.0" dependencies: @@ -15347,6 +16109,54 @@ __metadata: languageName: node linkType: hard +"d3@npm:^7.9.0": + version: 7.9.0 + resolution: "d3@npm:7.9.0" + dependencies: + d3-array: "npm:3" + d3-axis: "npm:3" + d3-brush: "npm:3" + d3-chord: "npm:3" + d3-color: "npm:3" + d3-contour: "npm:4" + d3-delaunay: "npm:6" + d3-dispatch: "npm:3" + d3-drag: "npm:3" + d3-dsv: "npm:3" + d3-ease: "npm:3" + d3-fetch: "npm:3" + d3-force: "npm:3" + d3-format: "npm:3" + d3-geo: "npm:3" + d3-hierarchy: "npm:3" + d3-interpolate: "npm:3" + d3-path: "npm:3" + d3-polygon: "npm:3" + d3-quadtree: "npm:3" + d3-random: "npm:3" + d3-scale: "npm:4" + d3-scale-chromatic: "npm:3" + d3-selection: "npm:3" + d3-shape: "npm:3" + d3-time: "npm:3" + d3-time-format: "npm:4" + d3-timer: "npm:3" + d3-transition: "npm:3" + d3-zoom: "npm:3" + checksum: 10c0/3dd9c08c73cfaa69c70c49e603c85e049c3904664d9c79a1a52a0f52795828a1ff23592dc9a7b2257e711d68a615472a13103c212032f38e016d609796e087e8 + languageName: node + linkType: hard + +"dagre-d3-es@npm:7.0.14": + version: 7.0.14 + resolution: "dagre-d3-es@npm:7.0.14" + dependencies: + d3: "npm:^7.9.0" + lodash-es: "npm:^4.17.21" + checksum: 10c0/0dc91fc79300eb0a4eab5a48a76c2baf3ce439c389d19e2f015729bb57dafd75e1e9a4c2880daf016e81ee45caca7b21745c13b23b6cd2a786ce84767e88323e + languageName: node + linkType: hard + "damerau-levenshtein@npm:^1.0.8": version: 1.0.8 resolution: "damerau-levenshtein@npm:1.0.8" @@ -15444,6 +16254,13 @@ __metadata: languageName: node linkType: hard +"dayjs@npm:^1.11.20": + version: 1.11.21 + resolution: "dayjs@npm:1.11.21" + checksum: 10c0/bd97dfdc4bfea3c66268635690313828b386faa040fbc1f829ff42a2bd748b72c9d9b3c8f9616ce9e61fcb78923f1461a462c969c54b1084458ae1b715898fb0 + languageName: node + linkType: hard + "debounce-promise@npm:^3.1.2": version: 3.1.2 resolution: "debounce-promise@npm:3.1.2" @@ -15657,6 +16474,15 @@ __metadata: languageName: node linkType: hard +"delaunator@npm:5": + version: 5.1.0 + resolution: "delaunator@npm:5.1.0" + dependencies: + robust-predicates: "npm:^3.0.2" + checksum: 10c0/6489e3598212ab8759575e30f3ac26063471846e25c779048f441f2ccefd25efb9a52275e7e8e3dcc5bf5bc5c35169cf1de27f985d359fd5a24057be88fd1817 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -15954,6 +16780,18 @@ __metadata: languageName: node linkType: hard +"dompurify@npm:^3.3.3": + version: 3.4.12 + resolution: "dompurify@npm:3.4.12" + dependencies: + "@types/trusted-types": "npm:^2.0.7" + dependenciesMeta: + "@types/trusted-types": + optional: true + checksum: 10c0/127a13817353d4e20e75a991a9022a04c3af12af7479f68e2b8bee6dbc7330a96edfb8f4ebff96f4f0f24cd43e8dbba46214131f510c3aa87a843bd8b610d0ab + languageName: node + linkType: hard + "domutils@npm:^2.5.2, domutils@npm:^2.8.0": version: 2.8.0 resolution: "domutils@npm:2.8.0" @@ -16438,6 +17276,20 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.45.1": + version: 1.49.0 + resolution: "es-toolkit@npm:1.49.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + vitepress-plugin-sandpack@1.1.4: + unplugged: true + checksum: 10c0/ab0864bb0c5c494ed09043d53a74b58a0ab9df1b89b9b54bce72a63de2869152d7d65e489dc89ab671f0fea243728922c8a8f8c873f1b2a53350a23360b3e2df + languageName: node + linkType: hard + "es6-error@npm:^4.1.1": version: 4.1.1 resolution: "es6-error@npm:4.1.1" @@ -18599,6 +19451,13 @@ __metadata: languageName: node linkType: hard +"hachure-fill@npm:^0.5.2": + version: 0.5.2 + resolution: "hachure-fill@npm:0.5.2" + checksum: 10c0/307e3b6f9f2d3c11a82099c3f71eecbb9c440c00c1f896ac1732c23e6dbff16a92bb893d222b8b721b89cf11e58649ca60b4c24e5663f705f877cefd40153429 + languageName: node + linkType: hard + "handle-thing@npm:^2.0.0": version: 2.0.1 resolution: "handle-thing@npm:2.0.1" @@ -19261,7 +20120,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -19413,6 +20272,13 @@ __metadata: languageName: node linkType: hard +"import-meta-resolve@npm:^4.2.0": + version: 4.2.0 + resolution: "import-meta-resolve@npm:4.2.0" + checksum: 10c0/3ee8aeecb61d19b49d2703987f977e9d1c7d4ba47db615a570eaa02fe414f40dfa63f7b953e842cbe8470d26df6371332bfcf21b2fd92b0112f9fea80dde2c4c + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -19515,6 +20381,20 @@ __metadata: languageName: node linkType: hard +"internmap@npm:1 - 2": + version: 2.0.3 + resolution: "internmap@npm:2.0.3" + checksum: 10c0/8cedd57f07bbc22501516fbfc70447f0c6812871d471096fad9ea603516eacc2137b633633daf432c029712df0baefd793686388ddf5737e3ea15074b877f7ed + languageName: node + linkType: hard + +"internmap@npm:^1.0.0": + version: 1.0.1 + resolution: "internmap@npm:1.0.1" + checksum: 10c0/60942be815ca19da643b6d4f23bd0bf4e8c97abbd080fb963fe67583b60bdfb3530448ad4486bae40810e92317bded9995cc31411218acc750d72cd4e8646eee + languageName: node + linkType: hard + "interpret@npm:^2.2.0": version: 2.2.0 resolution: "interpret@npm:2.2.0" @@ -21490,6 +22370,17 @@ __metadata: languageName: node linkType: hard +"katex@npm:^0.16.45": + version: 0.16.47 + resolution: "katex@npm:0.16.47" + dependencies: + commander: "npm:^8.3.0" + bin: + katex: cli.js + checksum: 10c0/b10f4d0651c60771a48444879e4227255e26e2b2ec061b1ee4b08934863ad2324ba8dbb772455f7768aeb14dfcc13bcd309174a0ddd5ef954a607f644a197710 + languageName: node + linkType: hard + "keytar@npm:^7.9.0": version: 7.9.0 resolution: "keytar@npm:7.9.0" @@ -21519,6 +22410,13 @@ __metadata: languageName: node linkType: hard +"khroma@npm:^2.1.0": + version: 2.1.0 + resolution: "khroma@npm:2.1.0" + checksum: 10c0/634d98753ff5d2540491cafeb708fc98de0d43f4e6795256d5c8f6e3ad77de93049ea41433928fda3697adf7bbe6fe27351858f6d23b78f8b5775ef314c59891 + languageName: node + linkType: hard + "kind-of@npm:^6.0.2": version: 6.0.3 resolution: "kind-of@npm:6.0.3" @@ -21633,6 +22531,20 @@ __metadata: languageName: node linkType: hard +"layout-base@npm:^1.0.0": + version: 1.0.2 + resolution: "layout-base@npm:1.0.2" + checksum: 10c0/2a55d0460fd9f6ed53d7e301b9eb3dea19bda03815d616a40665ce6dc75c1f4d62e1ca19a897da1cfaf6de1b91de59cd6f2f79ba1258f3d7fccc7d46ca7f3337 + languageName: node + linkType: hard + +"layout-base@npm:^2.0.0": + version: 2.0.1 + resolution: "layout-base@npm:2.0.1" + checksum: 10c0/a44df9ef3cbff9916a10f616635e22b5787c89fa62b2fec6f99e8e6ee512c7cebd22668ce32dab5a83c934ba0a309c51a678aa0b40d70853de6c357893c0a88b + languageName: node + linkType: hard + "lazystream@npm:^1.0.0": version: 1.0.1 resolution: "lazystream@npm:1.0.1" @@ -22229,6 +23141,15 @@ __metadata: languageName: node linkType: hard +"marked@npm:^16.3.0": + version: 16.4.2 + resolution: "marked@npm:16.4.2" + bin: + marked: bin/marked.js + checksum: 10c0/fc6051142172454f2023f3d6b31cca92879ec8e1b96457086a54c70354c74b00e1b6543a76a1fad6d399366f52b90a848f6ffb8e1d65a5baff87f3ba9b8f1847 + languageName: node + linkType: hard + "marked@npm:^4.0.10, marked@npm:^4.0.14": version: 4.3.0 resolution: "marked@npm:4.3.0" @@ -22567,6 +23488,35 @@ __metadata: languageName: node linkType: hard +"mermaid@npm:^11.6.0": + version: 11.16.0 + resolution: "mermaid@npm:11.16.0" + dependencies: + "@braintree/sanitize-url": "npm:^7.1.2" + "@iconify/utils": "npm:^3.0.2" + "@mermaid-js/parser": "npm:^1.2.0" + "@types/d3": "npm:^7.4.3" + "@upsetjs/venn.js": "npm:^2.0.0" + cytoscape: "npm:^3.33.3" + cytoscape-cose-bilkent: "npm:^4.1.0" + cytoscape-fcose: "npm:^2.2.0" + d3: "npm:^7.9.0" + d3-sankey: "npm:^0.12.3" + dagre-d3-es: "npm:7.0.14" + dayjs: "npm:^1.11.20" + dompurify: "npm:^3.3.3" + es-toolkit: "npm:^1.45.1" + katex: "npm:^0.16.45" + khroma: "npm:^2.1.0" + marked: "npm:^16.3.0" + roughjs: "npm:^4.6.6" + stylis: "npm:^4.3.6" + ts-dedent: "npm:^2.2.0" + uuid: "npm:^11.1.0 || ^12 || ^13 || ^14.0.0" + checksum: 10c0/a14f9bc9db7f1dea65b0d6c0b920236d12ad2812f2a1b11c8b39b3dfb3c22bfce39c77f6a69493203b85880d8008d345c539efe7ae6a31d3dad512833ccfb517 + languageName: node + linkType: hard + "meros@npm:^1.1.4": version: 1.3.2 resolution: "meros@npm:1.3.2" @@ -24394,6 +25344,13 @@ __metadata: languageName: node linkType: hard +"package-manager-detector@npm:^1.3.0": + version: 1.7.0 + resolution: "package-manager-detector@npm:1.7.0" + checksum: 10c0/49488e732ef854205b8c58f68f2315c5b1006169bf9b3a34ca3042c2995edf53e805ee720778f214f32bb80cf6e7cc1ac13508423e89decc691c28329ade6a7d + languageName: node + linkType: hard + "pako@npm:^1.0.10, pako@npm:~1.0.2, pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" @@ -24611,6 +25568,13 @@ __metadata: languageName: node linkType: hard +"path-data-parser@npm:0.1.0, path-data-parser@npm:^0.1.0": + version: 0.1.0 + resolution: "path-data-parser@npm:0.1.0" + checksum: 10c0/ba22d54669a8bc4a3df27431fe667900685585d1196085b803d0aa4066b83e709bbf2be7c1d2b56e706b49cc698231d55947c22abbfc4843ca424bbf8c985745 + languageName: node + linkType: hard + "path-equal@npm:^1.2.5": version: 1.2.5 resolution: "path-equal@npm:1.2.5" @@ -25038,6 +26002,23 @@ __metadata: languageName: node linkType: hard +"points-on-curve@npm:0.2.0, points-on-curve@npm:^0.2.0": + version: 0.2.0 + resolution: "points-on-curve@npm:0.2.0" + checksum: 10c0/f0d92343fcc2ad1f48334633e580574c1e0e28038a756133e171e537f270d6d64203feada5ee556e36f448a1b46e0306dee07b30f589f4e3ad720f6ee38ef48c + languageName: node + linkType: hard + +"points-on-path@npm:^0.2.1": + version: 0.2.1 + resolution: "points-on-path@npm:0.2.1" + dependencies: + path-data-parser: "npm:0.1.0" + points-on-curve: "npm:0.2.0" + checksum: 10c0/a7010340f9f196976f61838e767bb7b0b7f6273ab4fb9eb37c61001fe26fbfc3fcd63c96d5e85b9a4ab579213ab366f2ddaaf60e2a9253e2b91a62db33f395ba + languageName: node + linkType: hard + "pony-cause@npm:^1.1.1": version: 1.1.1 resolution: "pony-cause@npm:1.1.1" @@ -27435,6 +28416,13 @@ __metadata: languageName: node linkType: hard +"robust-predicates@npm:^3.0.2": + version: 3.0.3 + resolution: "robust-predicates@npm:3.0.3" + checksum: 10c0/ae23a0318be809545f091a076818747848f144495491e24e6df5d767f2bad0a1501bbeac34e78b74681d1437ecff0585f593ebfe6c8d49a50e79c5053b962693 + languageName: node + linkType: hard + "rollup-plugin-dts@npm:^6.1.0": version: 6.4.1 resolution: "rollup-plugin-dts@npm:6.4.1" @@ -27612,6 +28600,18 @@ __metadata: languageName: unknown linkType: soft +"roughjs@npm:^4.6.6": + version: 4.6.6 + resolution: "roughjs@npm:4.6.6" + dependencies: + hachure-fill: "npm:^0.5.2" + path-data-parser: "npm:^0.1.0" + points-on-curve: "npm:^0.2.0" + points-on-path: "npm:^0.2.1" + checksum: 10c0/68c11bf4516aa014cef2fe52426a9bab237c2f500d13e1a4f13b523cb5723667bf2d92b9619325efdc5bc2a193588ff5af8d51683df17cfb8720e96fe2b92b0c + languageName: node + linkType: hard + "router@npm:^2.2.0": version: 2.2.0 resolution: "router@npm:2.2.0" @@ -27657,6 +28657,13 @@ __metadata: languageName: node linkType: hard +"rw@npm:1": + version: 1.3.3 + resolution: "rw@npm:1.3.3" + checksum: 10c0/b1e1ef37d1e79d9dc7050787866e30b6ddcb2625149276045c262c6b4d53075ddc35f387a856a8e76f0d0df59f4cd58fe24707e40797ebee66e542b840ed6a53 + languageName: node + linkType: hard + "rxjs@npm:^7.5.5": version: 7.8.2 resolution: "rxjs@npm:7.8.2" @@ -28950,7 +29957,7 @@ __metadata: languageName: node linkType: hard -"stylis@npm:^4.3.0": +"stylis@npm:^4.3.0, stylis@npm:^4.3.6": version: 4.4.0 resolution: "stylis@npm:4.4.0" checksum: 10c0/259be096d90dfbfe903c8656dcb7591e52a421e577e950ef42ebd9ca02f387623a1165dd08761492fb6e92a7a562d62a53a694a10b0a2f6dcd7a0db107b4bf55 @@ -29475,6 +30482,13 @@ __metadata: languageName: node linkType: hard +"tinyexec@npm:^1.0.1": + version: 1.2.4 + resolution: "tinyexec@npm:1.2.4" + checksum: 10c0/153b8db6b080194b558ff145b9cffc36b80a6e07babd644dcfbe49c807eee668c876049d28bdee90b96304476f883352f2dad91b3f86bc23832532f4363e66ff + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.9": version: 0.2.17 resolution: "tinyglobby@npm:0.2.17" @@ -29707,6 +30721,13 @@ __metadata: languageName: node linkType: hard +"ts-dedent@npm:^2.2.0": + version: 2.3.0 + resolution: "ts-dedent@npm:2.3.0" + checksum: 10c0/bfc3331e0740191c0134fb526e7f01e16657e50955c9395de14703c6ef17119c91651fa044cf558dc9c1dbb0fe1b2a74e303aeebcbd5e3b31acd14f72f545a54 + languageName: node + linkType: hard + "ts-easing@npm:^0.2.0": version: 0.2.0 resolution: "ts-easing@npm:0.2.0" @@ -30578,6 +31599,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^11.1.0 || ^12 || ^13 || ^14.0.0": + version: 14.0.1 + resolution: "uuid@npm:14.0.1" + bin: + uuid: dist-node/bin/uuid + checksum: 10c0/2d961289097cb68c37d93d1da0b5c3aafc1eb9948a455cca8d0ae53a099b2fe583b8933254a84097f700e6bac2e23033364904df0467c22551d5d9611febcaf6 + languageName: node + linkType: hard + "uuid@npm:^3.4.0": version: 3.4.0 resolution: "uuid@npm:3.4.0"