@hraness/design-kit 0.40.1 → 0.40.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/MARKETING_COPY.md CHANGED
@@ -4,6 +4,18 @@ The product-marketing components give every Hraness site the same page shape. Th
4
4
 
5
5
  A reader arrives asking "What is this, and is it for me?" Answer that in the hero, show evidence next, and keep build details for the documentation.
6
6
 
7
+ ## Product names
8
+
9
+ Every product name is the exact display name from the portfolio messaging record, `messaging.names.name`. Use that value in headers, footers, heroes, related-product cards, social cards, metadata, README headings, and CLI banners. Preserve its case and punctuation: `PeopleBlade`, `TextButler`, `GhostGet`, `SlopCamera`, `SlopTrade`, `ALGAL`, `Sys1`, `Rough Day`, and `Hraness`. Intentionally lowercase names such as `aicharts`, `icon.place`, and `act60.me` stay lowercase.
10
+
11
+ Pass the display name unchanged to `MarketingSiteHeader.brand`, `MarketingSiteFooter.name`, `ProductHero.name`, and related-product `name` slots. Derive accessible labels from the same value, such as `${displayName} home`. Social-image declarations use it for both `name` and the visible `brand`; keep the domain in `domain`.
12
+
13
+ Commands, package names, repository names, domains, URL paths, anchor IDs, and audience keys are technical identifiers. Keep them separate and unchanged. `sys1.io` remains a domain, but its wordmark is `Sys1`; `rough.day` remains a domain, but its wordmark is `Rough Day`. A domain-shaped display name is valid only when the messaging record itself names the product that way.
14
+
15
+ Do not call `toLowerCase()` or `toUpperCase()` on a display name, and do not use CSS `text-transform` to restyle it. Source text must already contain the canonical form. Wordmark roles preserve source casing even when surrounding copy has a different typographic convention.
16
+
17
+ In public-page checks, pass the registry name as ``inspectMarketingHeader({ brandName: displayName, brandLabel: `${displayName} home` })``. `brandName` checks visible text independently of the accessible label and, in a rendered browser, rejects CSS casing transforms. Keep that expectation independent of the homepage's current text so the same mistake on every route cannot pass.
18
+
7
19
  ## Slots
8
20
 
9
21
  Limits are maximums. Count characters in the rendered text.
@@ -24,6 +36,7 @@ Limits are maximums. Count characters in the rendered text.
24
36
  | `MarketingCodeBlock` | Commands and output a reader can copy and run on the current release. Keep lines inside about 32 characters on a phone. | | Prompts, placeholders, or output the release cannot produce. |
25
37
  | `MarketingMarquee` `label` | One sentence with `{count}`, which renders as the number of items: "Works with {count} services". | 48 characters | Counting items the band does not show, rounded or "+" counts, and superlatives such as "every service". |
26
38
  | `MarketingMarquee` `items` | The services or sources the count covers, each under the name its own site uses or the name the product's source list gives it. Pass a registry mark, or a `generic` glyph for files and sites without a brand. | Name: 32 characters | Unreleased, unverified, or planned integrations; customer logos; marks for products the integration does not use. |
39
+ | `MarketingAccountActions` `primary` label | "Create account" for a signed-out visitor; "Open account" once they are signed in. The sign-in link always reads "Sign in". | | "Sign up", "Get started", "Join", or "Sign in with" a provider name on one site and a different label on another. |
27
40
  | `MarketingPillars`, `MarketingPrimitives` | Two to four items. Labels name a thing or state a fact ("A log for every run"); each summary is one sentence. | Label: five words. Summary: 120 characters | Adjective triads ("Fast / Legible / Yours") and abstract nouns ("durable objects"). |
28
41
  | Section `heading` | Sentence case. A full sentence in the editorial preset may end with a period; other headings do not. | 70 characters | Slogans and headings that promise more than the section shows. |
29
42
  | `MarketingTrustBoundary` | What stays on the reader's machine, what is shared, and what the product will not do, each stated once on the page. | Four items | Authority, custody, admission, or lease vocabulary. |
package/README.md CHANGED
@@ -11,7 +11,7 @@ Pin a GitHub release tag:
11
11
  ```json
12
12
  {
13
13
  "dependencies": {
14
- "@hraness/design-kit": "github:hraness/design-kit#v0.40.1",
14
+ "@hraness/design-kit": "github:hraness/design-kit#v0.40.2",
15
15
  "@hraness/ui": "github:hraness/ui#v0.5.17"
16
16
  }
17
17
  }
@@ -23,6 +23,59 @@ Pin a GitHub release tag:
23
23
  installation so the framework-neutral root and syntax highlighter can be used
24
24
  on their own. React 18 or 19 and React DOM 18 or 19 are also peer dependencies.
25
25
 
26
+ ## Render a first application header
27
+
28
+ In an existing React 18 or 19 application with the dependencies above installed,
29
+ load the complete precompiled stylesheet once in your global CSS file:
30
+
31
+ ```css
32
+ @import "@hraness/design-kit/styles.css";
33
+ ```
34
+
35
+ If you use Tailwind, put its import first. This route needs no application StyleX
36
+ compiler. It loads the shared presentation layers and default webfonts; do not
37
+ combine it with the compiler-adopter route described in
38
+ [Load the presentation layer](#load-the-presentation-layer).
39
+
40
+ In `App.tsx`, render a header and your application content:
41
+
42
+ ```tsx
43
+ import { TopBar } from "@hraness/design-kit/react";
44
+
45
+ export default function App() {
46
+ return (
47
+ <>
48
+ <TopBar title="My workspace" />
49
+ <main>
50
+ <h1>Saved work</h1>
51
+ <p>Your application owns the content and state.</p>
52
+ </main>
53
+ </>
54
+ );
55
+ }
56
+ ```
57
+
58
+ Run your application's existing development command. You see a solid, non-sticky
59
+ header titled “My workspace” above “Saved work”. `TopBar` renders a semantic
60
+ `header`; it does not supply application routing or a `main` landmark for you.
61
+
62
+ ## Find the right documentation
63
+
64
+ - [Load styles or adopt the StyleX compiler](#load-the-presentation-layer): choose one stylesheet route.
65
+ - [Use application compositions](#use-application-compositions): shells, navigation, and surfaces.
66
+ - [Explain a technical product](#explain-a-technical-product): marketing compositions and complete examples.
67
+ - [Publish articles](#publish-articles) and [article copy guidance](ARTICLE_COPY.md): article structure and review requirements.
68
+ - [Show status pages](#show-status-pages): error and not-found pages.
69
+ - [Use charts and syntax](#use-charts-and-syntax): application-owned data and code display.
70
+ - [Appearance and fonts](#appearance-and-fonts) and [palette reference](PALETTES.md): themes and typography.
71
+ - [Run the gallery](#gallery) or [develop the package](#development).
72
+
73
+ ## Release notes and focused examples
74
+
75
+ ### Portfolio snapshot refresh
76
+
77
+ Version 0.40.2 refreshes the `@hraness/design-kit/portfolio` snapshot from registry commit `26b167cd`. It adds the Alt, midi.place, and Textmock products and the `runtime:xcb:aicharts:installs` and `runtime:gobstopper:aicharts:installs` relations, which fold the retired `contract:xcb:aicharts:exports-sessions-for` entry into each installer's detail sentence. Sites that render a "How X uses aicharts" post can now resolve the relation their admission names.
78
+
26
79
  ### Article links and account actions
27
80
 
28
81
  Version 0.40.1 strengthens the dotted underline on embedded article author links during hover and keyboard focus. Account prompts in plain pages retain a readable Create account button and a dotted Sign in link, with visible keyboard focus and system colors in high contrast mode.
@@ -595,6 +648,8 @@ On screens that allow motion, the band scrolls slowly toward the start of the li
595
648
 
596
649
  `MarketingAccount` gives account access a full section with a heading, short summary, and content slot. `MarketingAccountActions` pairs a prominent `primary` link with an optional `signIn` link; both have 56px minimum touch targets. Product authentication forms and session state remain in the consuming site. Add a direct account link to the site's header so visitors can find it without scrolling. Prose links and `.hraness-text-link` use subtle dotted underlines; header navigation and primary buttons retain their own presentation.
597
650
 
651
+ Wherever a signed-out visitor needs an account, offer the same two choices with `MarketingAccountActions`: a `primary` link labeled “Create account” and the `signIn` link, which reads “Sign in”. This covers the account section and any page that asks a visitor to sign in before it shows private content. When one sign-in flow creates new accounts and signs in existing ones, both links may point to it. Place the actions directly in the section or page, not inside a card, panel, or other surface: Sign in is a text link, and a surrounding surface makes it look like an oversized button.
652
+
598
653
  `ArticleIndex` lists posts, `ArticleCallout` marks a note, limit, or warning, and `ArticleRelatedProducts` wraps `MarketingRelated`. Static site builders import `renderArticleHtml`, `renderArticleIndexHtml`, `renderArticleSourcesHtml`, `renderArticleCalloutHtml`, and `renderArticleRelatedHtml` from the framework-neutral root and load `@hraness/design-kit/plain-publication.css` after `plain-site.css`. Text arguments are escaped; `bodyHtml` and `afterHtml` take HTML the site already rendered.
599
654
 
600
655
  Each host keeps an `ArticleAdmission` record per article and checks the registry in a test:
@@ -894,7 +949,7 @@ bun run browser:install
894
949
  bun run check
895
950
  ```
896
951
 
897
- The stable dependency pair for this release is `@hraness/ui` `v0.5.17` with `@hraness/design-kit` `v0.40.1`. Version 0.31.0 keeps the `limits` beat and beats marked `social: false` out of the social kit and adds `socialPost` for social wording that stands without a caveat. Version 0.30.3 refreshes the portfolio snapshot so related-product cards use each product's own spelling, such as GhostGet and TextButler. Version 0.30.2 keeps the narrow and stacked install-tab layout when another package compiles the same atoms into a later cascade layer. Version 0.30.1 keeps every PlatformInstall tab name whole in columns down to 200px by stacking each mark above its name, using a container query on the component. Version 0.30.0 adds `site-shell.css`, which keeps short-page footers at the viewport bottom. Version 0.29.3 preserves readable selected install tabs in forced colors. Version 0.29.2 keeps all three PlatformInstall tabs visible at 320 to 360px and draws each platform mark once per component. Version 0.29.1 keeps marketing action labels readable in forced colors. Version 0.29.0 adds `PlatformInstall`, one install block for every CLI site: a tab per operating system with its mark, the install command with a Copy button that announces the result, optional alternative commands such as npm or Homebrew, and a note for platforms without a native build. After hydration it selects the visitor's operating system; without JavaScript every command shows. It also adds `PlatformIcon` (Apple, Tux, and Windows marks in `currentColor`) and a `PlatformBadges` "Runs on" row, plus `platformLabel`, `platformMark`, `detectPlatform`, and `matchDetectedPlatform` at the package root. See [Install commands for each platform](#install-commands-for-each-platform). No existing export changes. Version 0.28.0 adds the launch kit. `@hraness/design-kit/mockups` draws labelled illustrations of chat, feeds, inboxes, articles, terminals, browsers, desktop windows, menu bars, and phones in server-safe plain React with no StyleX or React Aria, styled by `@hraness/design-kit/mockups.css`; each renders as one image with a text description and no headings. `@hraness/design-kit/mockups/client` adds `ModeShowcase`, `FitToWidth`, and `StepThrough`. `@hraness/design-kit/launch`, with no React, holds the `LaunchBeat`, `LaunchFacts`, and `SocialKit` shapes with `resolveLaunchBeats`, `buildSocialKit`, and `assertLaunchKit`. `@hraness/design-kit/testing` gives product repositories `blogConformance`, `renderMatrix`, `assertNoHeadings`, `assertRoleImgWithLabel`, and `assertFakeHandles`. The React entries add `ArticleFigure`, `ArticleVideo` with `articleVideoJsonLd`, `ArticleTable`, `ArticleBarChart`, `ComparisonTable`, `LaunchBeats`, and `SocialKitPanel`, and `MarketingProofFrame` takes `chrome` (`window`, `browser` with `url`, or `terminal`). [ARTICLE_COPY.md](ARTICLE_COPY.md) now writes "Introducing a product" as beats; the admission rules are unchanged. No existing export changes. Version 0.27.0 adds explicit Rust, TOML, YAML, Lean, and TLA+ code highlighting, including nested comments and multiline strings. The existing highlighter API and stylesheet remain the shared entry points; unsupported languages still render as escaped text. Version 0.26.0 adds `MarketingNotice` and the raw `.hraness-marketing-notice` class: one status or alert line (`info`, `success`, or `error`) that sits on the content edge of the page column instead of spanning the window. Errors are announced as alerts and other tones as status. Signed-in account pages that render inside `MarketingSiteHeader` should compose `MarketingMain`, `MarketingNotice`, `MarketingStatStrip`, and `MarketingSection` so every block shares the header's measure and gutter, rather than hand-rolled full-bleed banners and nested cards. Version 0.25.0 moves bordered foil surfaces off the spectrum: `.hraness-foil` and `[data-emphasis="primary"]` actions keep their flat surface fill under one theme-aware monochrome edge — black on light, white on dark, overridable through the new `--hraness-foil-edge` token — while the metallic spectrum stays on wordmarks and marks. The foil material contract advances to version 3: `surfaceImage` and `surfaceBackgroundClip` are replaced by `surfaceFill`, `edge`, `edgeDark`, and `edgeColor`. Reinstall any vendored marketing snapshot from the 0.25.0 commit. Version 0.24.0 joins a marketing footer directly followed by the shared `@hraness/site-footer` network footer into one band: the product row's bottom space collapses to a compact gap and the network row's content follows the marketing measure and gutter through `--hraness-site-footer-measure`, so product links and the organization row share one column instead of reading as two stacked bars. Mount the network footer directly after `MarketingSiteFooter`; no prop or markup change is needed inside either landmark. Version 0.23.0 moves marketing pages to the Quiet direction described in [DESIGN.md](DESIGN.md). `ProductHero` no longer renders a backdrop, `HeroBackdrop` renders nothing, and `attachHeroLight` is an inert disposer; their names and props stay so existing code compiles and are marked deprecated. The `cells`, `weave`, `contour`, and `mesh` patterns render as `none`, and marketing fields and Lantern walls paint the flat palette background. Both marketing presets use Nebula Sans for display headings (editorial at weight 550); Instrument Serif stays vendored for explicit opt-in only. Hero eyebrows are plain labels, the accent band loses its grid, and cards and header chrome use hairline edges instead of lifted shadows. On phones `MarketingSiteHeader` keeps the brand, primary action, and appearance menu on one row and moves the links to a second row that scrolls sideways, with 44px targets. To migrate, delete `backdrop` artwork, `HeroBackdrop`, `attachHeroLight`, pattern values, and product CSS that recreated textures or serif headings, then reinstall any vendored marketing snapshot from the 0.23.0 commit. Version 0.22.2 restores the canonical roughday mark — the rain-cloud artwork pinned by the portfolio registry — after the mark slot briefly carried a stray illustration. Version 0.22.1 completes the icon library with the roughday inline chip family (65 admitted assets, no pending members). Version 0.22.0 adds the `./icons` surface: 62 vetted single-ink assets across ten sets — a shared illustration family, product illustration families, and the product marks, each admitted through a measured gate (single ink, bounded aspect, coverage, stroke, paths, bytes) and per-set family coherence, distributed as a typed registry module (`hranessIcons`, `hranessIcon`, `hranessIconMarkup`, `hranessIconsForSet`) and as canonical `./icons/<set>/<slug>.svg` files for image consumers. See [ICONS.md](ICONS.md). Version 0.21.1 accepts status-page `routes` straight from a sitemap: long titles are shortened for the "Did you mean" line and unusable entries are dropped instead of failing the render. Version 0.21.0 replaces the 404 and route-error pages with one shared status page: the product's main action, a "Did you mean" link to the closest known page, at most three next links with one-line descriptions, an optional line for AI agents, and a glyph drawn as dots that gather, move away from the pointer, and settle. `RouteNotFoundPage`, `RouteErrorPage`, and `GlobalErrorDocument` render it; `renderStatusPageHtml` and `attachStatusPage` bring the same page to static sites; `status-page.css` ships in `styles.css` and `compiler-foundation.css`. The default copy changes to "We can’t find that page". See [STATUS_PAGES.md](STATUS_PAGES.md). Version 0.20.0 gives `ThemeMenuButton` the Lantern material: under `data-hraness-material="lantern"` its trigger is raised at rest and inset while pressed, and its menu uses the material plane, lift and warm selection, with no new props. Sites can delete their local Lantern CSS for the appearance menu. It also adds `formatRelativeTime` at the package root and a hydration-safe `RelativeTime` component in `@hraness/design-kit/react`. Version 0.19.0 redraws related-product cards as the hraness.com project cards: each shows the product's mark, its name, and its one-line `role` at reading size, and no longer renders the `relationship` sentence (the prop stays accepted and is deprecated). `MarketingRelatedProduct` and the static `ArticleRelatedLink` take a `mark`, and every `@hraness/design-kit/portfolio` product and `relatedFor()` item now carries its portfolio mark as an inert `data:image/svg+xml` URL. Related-tier and proof headings move to the new `--hraness-marketing-h3-size` token, so the editorial display face never renders below 1.75rem. `typography.css` gains per-level heading tokens (`--hraness-type-h1-font` through `--hraness-type-h4-font`, the matching `-weight` tokens, `--hraness-type-subheading-font`, and `--hraness-type-display-min`). h3 and h4 in `.hraness-prose` and publication articles now use the text face, and the h2 floor rises to 1.75rem. Version 0.18.3 adds the Sponge and Wordcell runtime relations to Oh to the `@hraness/design-kit/portfolio` snapshot, so related-product cards on all three sites can link them. Version 0.18.2 refreshes the `@hraness/design-kit/portfolio` snapshot from the registry: the public ghostget.com entry, updated Gobstopper and xcb naming and descriptions, and the current sibling-product relations for related-product cards. Version 0.18.1 adds the Perplexity mark and a dependency-free `@hraness/design-kit/provider-marks` leaf entry (`providerMark`, `providerMarks`, `providerMarkFallback`, `providerMarkGlyphDataUri`, `providerMarkArtDataUri`, `providerMarkOnAccent`, `providerMarkMonogram`) so packages such as `@hraness/ui` can consume the registry without pulling the marketing surface. Version 0.18.0 adds the shared provider-mark registry: `providerMarks`, `providerMark()` alias resolution, `ProviderMark`/`ProviderMarkChip` accent-tinted tile components on both React entry points, vendored agent and vendor artwork from LobeHub icons 1.95.1 plus documented Crush and Aider marks, monogram fallbacks for uncovered names, and data-URI helpers for CSS-mask consumers. See `vendor/provider-marks/UPSTREAM.md` for asset provenance. Version 0.17.2 carries the canonical portfolio messaging record per product (`names`, `category`, `tagline`, `short`, `meta`, `medium`, `long`, and hero copy) in the `/portfolio` snapshot. Version 0.17.1 lets Next.js apps that compile dependencies with Babel build the article layer: its link check no longer uses a Unicode property escape that Babel cannot rewrite, and it rejects the same control characters and whitespace as before. Version 0.17.0 adds the article layer: server-safe `MarketingArticle`, byline, provenance, sources, callout, related-product, and index components, a matching static HTML renderer for sites without React, long-form article styles in `plain-publication.css`, and the `ArticleAdmission` rubric with `assertArticleAdmissions()`. It also adds `@hraness/design-kit/portfolio`, a snapshot of public product names, one-liners, links, and relations for related-product cards and "How X uses Y" posts. See [ARTICLE_COPY.md](ARTICLE_COPY.md). Version 0.16.4 keeps native appearance-menu labels usable inside keyboard-focusable page landmarks, including mouse and touch selection. Version 0.16.3 keeps decorative hero backgrounds hidden in forced colors and reduced transparency when other packages load their styles afterward. Version 0.16.2 preserves palette hues in translucent headers, material surfaces, and decorative highlights. Version 0.16.1 keeps plain reading pages and nested compiled surfaces in their selected palette, including system appearance without JavaScript. Version 0.16.0 adds a shared bounded hero light, product-owned backdrop slots, five Lantern patterns, palette-derived soft surfaces, and responsive typography across marketing and reading layouts. Static sites can use the palette bridge for system appearance before JavaScript. See [HERO_FIELDS.md](HERO_FIELDS.md), [LANTERN_MATERIAL.md](LANTERN_MATERIAL.md), and [MARKETING_PRESET.md](MARKETING_PRESET.md). Version 0.15.0 lets `MarketingRelated` present labeled tiers of sibling products: a `groups` collection renders each tier under its own heading with an accessible card-row label, while the flat `items` shape stays available for a single group. Version 0.14.0 adds `MarketingRelated`, a collection section that presents sibling products as linked cards, each framed by its relationship to the featured product. Version 0.13.0 publishes `--hraness-sticky-offset` from sticky marketing chrome, gives `MarketingMain` and the next sticky sibling a clearance contract, stretches marketing card rows to the tallest item with a reserved two-line meta block, and clips per-card art wells so a logo surface cannot paint through the gutter. Version 0.12.0 replaces pointer-driven gradient rotation with a steady material and a moving light: the spectrum and its 115deg direction stay fixed while `--hraness-foil-x`/`--hraness-foil-y` highlights travel across each lockup, and marketing footers can opt into the same icon-plus-wordmark foil as the site header with `brandMark`. Version 0.11.1 preserves visible metallic marks when another package repeats a generic hidden atom in a later CSS layer. React consumers load `components.css` or `styles.css`; the raw marketing entry supports authored HTML hooks. Version 0.11 adds server-rendered `FoilMark` artwork and metallic text with subtle rainbow reflections, including a shared header mark seam and original-artwork fallbacks. Version 0.10.1 adds conservative server syntax defaults, includes their styles in the narrow marketing entry, and pins the icon dependency to preserve fresh Linux installs. Version 0.10 adds the shared foil contract: `.hraness-foil` surfaces and `.hraness-foil-text` wordmarks render a pointer-following metallic spectrum from the `--hraness-foil-*` custom properties, applied by default to marketing header brands and primary actions. The `attachFoil` browser export drives the bounded `x`/`y`/`angle` inputs with damped easing, reduced-motion and forced-color fallbacks, and no style injection; the same spectrum feeds `@hraness/site-footer` signup controls. Dark appearances use a deeper palette so the sheen stays visible. Version 0.8 removes Jelly's optional API, stylesheet, vendor runtime and theme-provider side effect. Migrate direct Jelly surfaces to native shared primitives before upgrading. Lantern now uses softer directional depth and shaded faces; the marketing preset adds individually shaded static cells, theme-aware terminal colors and window chrome. Code blocks retain source lines and follow the active palette. Paper preferences, semantic palettes, and compiler identity stay stable. Compiler adopters must regenerate their finalized stylesheet with the new package manifest.
952
+ The stable dependency pair for this release is `@hraness/ui` `v0.5.17` with `@hraness/design-kit` `v0.40.2`. Version 0.31.0 keeps the `limits` beat and beats marked `social: false` out of the social kit and adds `socialPost` for social wording that stands without a caveat. Version 0.30.3 refreshes the portfolio snapshot so related-product cards use each product's own spelling, such as GhostGet and TextButler. Version 0.30.2 keeps the narrow and stacked install-tab layout when another package compiles the same atoms into a later cascade layer. Version 0.30.1 keeps every PlatformInstall tab name whole in columns down to 200px by stacking each mark above its name, using a container query on the component. Version 0.30.0 adds `site-shell.css`, which keeps short-page footers at the viewport bottom. Version 0.29.3 preserves readable selected install tabs in forced colors. Version 0.29.2 keeps all three PlatformInstall tabs visible at 320 to 360px and draws each platform mark once per component. Version 0.29.1 keeps marketing action labels readable in forced colors. Version 0.29.0 adds `PlatformInstall`, one install block for every CLI site: a tab per operating system with its mark, the install command with a Copy button that announces the result, optional alternative commands such as npm or Homebrew, and a note for platforms without a native build. After hydration it selects the visitor's operating system; without JavaScript every command shows. It also adds `PlatformIcon` (Apple, Tux, and Windows marks in `currentColor`) and a `PlatformBadges` "Runs on" row, plus `platformLabel`, `platformMark`, `detectPlatform`, and `matchDetectedPlatform` at the package root. See [Install commands for each platform](#install-commands-for-each-platform). No existing export changes. Version 0.28.0 adds the launch kit. `@hraness/design-kit/mockups` draws labelled illustrations of chat, feeds, inboxes, articles, terminals, browsers, desktop windows, menu bars, and phones in server-safe plain React with no StyleX or React Aria, styled by `@hraness/design-kit/mockups.css`; each renders as one image with a text description and no headings. `@hraness/design-kit/mockups/client` adds `ModeShowcase`, `FitToWidth`, and `StepThrough`. `@hraness/design-kit/launch`, with no React, holds the `LaunchBeat`, `LaunchFacts`, and `SocialKit` shapes with `resolveLaunchBeats`, `buildSocialKit`, and `assertLaunchKit`. `@hraness/design-kit/testing` gives product repositories `blogConformance`, `renderMatrix`, `assertNoHeadings`, `assertRoleImgWithLabel`, and `assertFakeHandles`. The React entries add `ArticleFigure`, `ArticleVideo` with `articleVideoJsonLd`, `ArticleTable`, `ArticleBarChart`, `ComparisonTable`, `LaunchBeats`, and `SocialKitPanel`, and `MarketingProofFrame` takes `chrome` (`window`, `browser` with `url`, or `terminal`). [ARTICLE_COPY.md](ARTICLE_COPY.md) now writes "Introducing a product" as beats; the admission rules are unchanged. No existing export changes. Version 0.27.0 adds explicit Rust, TOML, YAML, Lean, and TLA+ code highlighting, including nested comments and multiline strings. The existing highlighter API and stylesheet remain the shared entry points; unsupported languages still render as escaped text. Version 0.26.0 adds `MarketingNotice` and the raw `.hraness-marketing-notice` class: one status or alert line (`info`, `success`, or `error`) that sits on the content edge of the page column instead of spanning the window. Errors are announced as alerts and other tones as status. Signed-in account pages that render inside `MarketingSiteHeader` should compose `MarketingMain`, `MarketingNotice`, `MarketingStatStrip`, and `MarketingSection` so every block shares the header's measure and gutter, rather than hand-rolled full-bleed banners and nested cards. Version 0.25.0 moves bordered foil surfaces off the spectrum: `.hraness-foil` and `[data-emphasis="primary"]` actions keep their flat surface fill under one theme-aware monochrome edge — black on light, white on dark, overridable through the new `--hraness-foil-edge` token — while the metallic spectrum stays on wordmarks and marks. The foil material contract advances to version 3: `surfaceImage` and `surfaceBackgroundClip` are replaced by `surfaceFill`, `edge`, `edgeDark`, and `edgeColor`. Reinstall any vendored marketing snapshot from the 0.25.0 commit. Version 0.24.0 joins a marketing footer directly followed by the shared `@hraness/site-footer` network footer into one band: the product row's bottom space collapses to a compact gap and the network row's content follows the marketing measure and gutter through `--hraness-site-footer-measure`, so product links and the organization row share one column instead of reading as two stacked bars. Mount the network footer directly after `MarketingSiteFooter`; no prop or markup change is needed inside either landmark. Version 0.23.0 moves marketing pages to the Quiet direction described in [DESIGN.md](DESIGN.md). `ProductHero` no longer renders a backdrop, `HeroBackdrop` renders nothing, and `attachHeroLight` is an inert disposer; their names and props stay so existing code compiles and are marked deprecated. The `cells`, `weave`, `contour`, and `mesh` patterns render as `none`, and marketing fields and Lantern walls paint the flat palette background. Both marketing presets use Nebula Sans for display headings (editorial at weight 550); Instrument Serif stays vendored for explicit opt-in only. Hero eyebrows are plain labels, the accent band loses its grid, and cards and header chrome use hairline edges instead of lifted shadows. On phones `MarketingSiteHeader` keeps the brand, primary action, and appearance menu on one row and moves the links to a second row that scrolls sideways, with 44px targets. To migrate, delete `backdrop` artwork, `HeroBackdrop`, `attachHeroLight`, pattern values, and product CSS that recreated textures or serif headings, then reinstall any vendored marketing snapshot from the 0.23.0 commit. Version 0.22.2 restores the canonical roughday mark — the rain-cloud artwork pinned by the portfolio registry — after the mark slot briefly carried a stray illustration. Version 0.22.1 completes the icon library with the roughday inline chip family (65 admitted assets, no pending members). Version 0.22.0 adds the `./icons` surface: 62 vetted single-ink assets across ten sets — a shared illustration family, product illustration families, and the product marks, each admitted through a measured gate (single ink, bounded aspect, coverage, stroke, paths, bytes) and per-set family coherence, distributed as a typed registry module (`hranessIcons`, `hranessIcon`, `hranessIconMarkup`, `hranessIconsForSet`) and as canonical `./icons/<set>/<slug>.svg` files for image consumers. See [ICONS.md](ICONS.md). Version 0.21.1 accepts status-page `routes` straight from a sitemap: long titles are shortened for the "Did you mean" line and unusable entries are dropped instead of failing the render. Version 0.21.0 replaces the 404 and route-error pages with one shared status page: the product's main action, a "Did you mean" link to the closest known page, at most three next links with one-line descriptions, an optional line for AI agents, and a glyph drawn as dots that gather, move away from the pointer, and settle. `RouteNotFoundPage`, `RouteErrorPage`, and `GlobalErrorDocument` render it; `renderStatusPageHtml` and `attachStatusPage` bring the same page to static sites; `status-page.css` ships in `styles.css` and `compiler-foundation.css`. The default copy changes to "We can’t find that page". See [STATUS_PAGES.md](STATUS_PAGES.md). Version 0.20.0 gives `ThemeMenuButton` the Lantern material: under `data-hraness-material="lantern"` its trigger is raised at rest and inset while pressed, and its menu uses the material plane, lift and warm selection, with no new props. Sites can delete their local Lantern CSS for the appearance menu. It also adds `formatRelativeTime` at the package root and a hydration-safe `RelativeTime` component in `@hraness/design-kit/react`. Version 0.19.0 redraws related-product cards as the hraness.com project cards: each shows the product's mark, its name, and its one-line `role` at reading size, and no longer renders the `relationship` sentence (the prop stays accepted and is deprecated). `MarketingRelatedProduct` and the static `ArticleRelatedLink` take a `mark`, and every `@hraness/design-kit/portfolio` product and `relatedFor()` item now carries its portfolio mark as an inert `data:image/svg+xml` URL. Related-tier and proof headings move to the new `--hraness-marketing-h3-size` token, so the editorial display face never renders below 1.75rem. `typography.css` gains per-level heading tokens (`--hraness-type-h1-font` through `--hraness-type-h4-font`, the matching `-weight` tokens, `--hraness-type-subheading-font`, and `--hraness-type-display-min`). h3 and h4 in `.hraness-prose` and publication articles now use the text face, and the h2 floor rises to 1.75rem. Version 0.18.3 adds the Sponge and Wordcell runtime relations to Oh to the `@hraness/design-kit/portfolio` snapshot, so related-product cards on all three sites can link them. Version 0.18.2 refreshes the `@hraness/design-kit/portfolio` snapshot from the registry: the public ghostget.com entry, updated Gobstopper and xcb naming and descriptions, and the current sibling-product relations for related-product cards. Version 0.18.1 adds the Perplexity mark and a dependency-free `@hraness/design-kit/provider-marks` leaf entry (`providerMark`, `providerMarks`, `providerMarkFallback`, `providerMarkGlyphDataUri`, `providerMarkArtDataUri`, `providerMarkOnAccent`, `providerMarkMonogram`) so packages such as `@hraness/ui` can consume the registry without pulling the marketing surface. Version 0.18.0 adds the shared provider-mark registry: `providerMarks`, `providerMark()` alias resolution, `ProviderMark`/`ProviderMarkChip` accent-tinted tile components on both React entry points, vendored agent and vendor artwork from LobeHub icons 1.95.1 plus documented Crush and Aider marks, monogram fallbacks for uncovered names, and data-URI helpers for CSS-mask consumers. See `vendor/provider-marks/UPSTREAM.md` for asset provenance. Version 0.17.2 carries the canonical portfolio messaging record per product (`names`, `category`, `tagline`, `short`, `meta`, `medium`, `long`, and hero copy) in the `/portfolio` snapshot. Version 0.17.1 lets Next.js apps that compile dependencies with Babel build the article layer: its link check no longer uses a Unicode property escape that Babel cannot rewrite, and it rejects the same control characters and whitespace as before. Version 0.17.0 adds the article layer: server-safe `MarketingArticle`, byline, provenance, sources, callout, related-product, and index components, a matching static HTML renderer for sites without React, long-form article styles in `plain-publication.css`, and the `ArticleAdmission` rubric with `assertArticleAdmissions()`. It also adds `@hraness/design-kit/portfolio`, a snapshot of public product names, one-liners, links, and relations for related-product cards and "How X uses Y" posts. See [ARTICLE_COPY.md](ARTICLE_COPY.md). Version 0.16.4 keeps native appearance-menu labels usable inside keyboard-focusable page landmarks, including mouse and touch selection. Version 0.16.3 keeps decorative hero backgrounds hidden in forced colors and reduced transparency when other packages load their styles afterward. Version 0.16.2 preserves palette hues in translucent headers, material surfaces, and decorative highlights. Version 0.16.1 keeps plain reading pages and nested compiled surfaces in their selected palette, including system appearance without JavaScript. Version 0.16.0 adds a shared bounded hero light, product-owned backdrop slots, five Lantern patterns, palette-derived soft surfaces, and responsive typography across marketing and reading layouts. Static sites can use the palette bridge for system appearance before JavaScript. See [HERO_FIELDS.md](HERO_FIELDS.md), [LANTERN_MATERIAL.md](LANTERN_MATERIAL.md), and [MARKETING_PRESET.md](MARKETING_PRESET.md). Version 0.15.0 lets `MarketingRelated` present labeled tiers of sibling products: a `groups` collection renders each tier under its own heading with an accessible card-row label, while the flat `items` shape stays available for a single group. Version 0.14.0 adds `MarketingRelated`, a collection section that presents sibling products as linked cards, each framed by its relationship to the featured product. Version 0.13.0 publishes `--hraness-sticky-offset` from sticky marketing chrome, gives `MarketingMain` and the next sticky sibling a clearance contract, stretches marketing card rows to the tallest item with a reserved two-line meta block, and clips per-card art wells so a logo surface cannot paint through the gutter. Version 0.12.0 replaces pointer-driven gradient rotation with a steady material and a moving light: the spectrum and its 115deg direction stay fixed while `--hraness-foil-x`/`--hraness-foil-y` highlights travel across each lockup, and marketing footers can opt into the same icon-plus-wordmark foil as the site header with `brandMark`. Version 0.11.1 preserves visible metallic marks when another package repeats a generic hidden atom in a later CSS layer. React consumers load `components.css` or `styles.css`; the raw marketing entry supports authored HTML hooks. Version 0.11 adds server-rendered `FoilMark` artwork and metallic text with subtle rainbow reflections, including a shared header mark seam and original-artwork fallbacks. Version 0.10.1 adds conservative server syntax defaults, includes their styles in the narrow marketing entry, and pins the icon dependency to preserve fresh Linux installs. Version 0.10 adds the shared foil contract: `.hraness-foil` surfaces and `.hraness-foil-text` wordmarks render a pointer-following metallic spectrum from the `--hraness-foil-*` custom properties, applied by default to marketing header brands and primary actions. The `attachFoil` browser export drives the bounded `x`/`y`/`angle` inputs with damped easing, reduced-motion and forced-color fallbacks, and no style injection; the same spectrum feeds `@hraness/site-footer` signup controls. Dark appearances use a deeper palette so the sheen stays visible. Version 0.8 removes Jelly's optional API, stylesheet, vendor runtime and theme-provider side effect. Migrate direct Jelly surfaces to native shared primitives before upgrading. Lantern now uses softer directional depth and shaded faces; the marketing preset adds individually shaded static cells, theme-aware terminal colors and window chrome. Code blocks retain source lines and follow the active palette. Paper preferences, semantic palettes, and compiler identity stay stable. Compiler adopters must regenerate their finalized stylesheet with the new package manifest.
898
953
 
899
954
  The complete check runs linting, typechecking, production builds, an installed-package smoke test, deterministic examples, property tests, server rendering, vendor-integrity checks, and headless Chromium regressions. The browser gate verifies responsive shell ownership, extracted AnimatedRailStage, Fader, layout-surface, and playback-transport delivery, reduced-motion stage fallback, Fader keyboard and focus behavior, forced-color behavior, keyboard-operable appearance, browser-chrome synchronization across opposing device and saved preferences, global-error static metadata and runtime lifecycle, accessible title and copy, deterministic procedural layers, viewport containment, and the absence of the excluded canvas effect. Provision the pinned Chromium with `bun run browser:install`. An explicit `CHROMIUM_EXECUTABLE_PATH` must resolve to a provisioned Chrome for Testing; the browser gate rejects installed auto-updating Chrome.
900
955
 
@@ -1548,6 +1548,9 @@ function inspectMarketingHeader(options = {}, document = globalThis.document) {
1548
1548
  const image = mark?.querySelector("img");
1549
1549
  const brandHref = brand?.getAttribute("href") ?? null;
1550
1550
  const brandLabel = (brand?.getAttribute("aria-label") ?? brand?.textContent)?.trim() || null;
1551
+ const brandCopy = brand?.cloneNode(true);
1552
+ brandCopy?.querySelectorAll(".hraness-foil-mark, svg, img").forEach((element) => element.remove());
1553
+ const brandName = brandCopy?.textContent?.replace(/\s+/gu, " ").trim() || null;
1551
1554
  const brandMark = image?.getAttribute("src") ?? null;
1552
1555
  const nav = header?.querySelector("nav.hraness-marketing-header__nav");
1553
1556
  const links = [...nav?.querySelectorAll("a[href]") ?? []].map((link) => ({
@@ -1563,6 +1566,8 @@ function inspectMarketingHeader(options = {}, document = globalThis.document) {
1563
1566
  problems.push("The product home link is missing or points to a different page.");
1564
1567
  if (brandLabel === null || options.brandLabel !== undefined && brandLabel !== options.brandLabel)
1565
1568
  problems.push("The product home link has a missing or inconsistent name.");
1569
+ if (options.brandName !== undefined && brandName !== options.brandName)
1570
+ problems.push("The visible product wordmark does not match its canonical display name.");
1566
1571
  if (brand?.hasAttribute("data-foil") !== true || mark === null || mark === undefined || image === null || image === undefined || !mark.querySelector(".hraness-foil-mark__paint") || !brandMark) {
1567
1572
  problems.push("The product home link is missing its foil mark and artwork fallback.");
1568
1573
  } else if (options.brandMark !== undefined && brandMark !== options.brandMark) {
@@ -1599,6 +1604,32 @@ function inspectMarketingHeader(options = {}, document = globalThis.document) {
1599
1604
  if (box2.width <= 0 || box2.height <= 0 || hidden)
1600
1605
  problems.push(`The product ${name} is not visible.`);
1601
1606
  }
1607
+ if (options.brandName !== undefined && brand) {
1608
+ const textNodes = [];
1609
+ const walker = document.createTreeWalker(brand, 4);
1610
+ for (let node = walker.nextNode();node !== null; node = walker.nextNode()) {
1611
+ if (node.parentElement && !node.parentElement.closest(".hraness-foil-mark, svg, img"))
1612
+ textNodes.push(node);
1613
+ }
1614
+ if (textNodes.some((node) => node.textContent?.trim() && node.parentElement && view.getComputedStyle(node.parentElement).textTransform !== "none")) {
1615
+ problems.push("The product wordmark changes canonical casing with CSS.");
1616
+ }
1617
+ const renderedName = textNodes.filter((node) => {
1618
+ const range = document.createRange();
1619
+ range.selectNodeContents(node);
1620
+ const box2 = range.getBoundingClientRect();
1621
+ if (box2.width <= 0 || box2.height <= 0)
1622
+ return false;
1623
+ for (let ancestor = node.parentElement;ancestor !== null; ancestor = ancestor.parentElement) {
1624
+ const style = view.getComputedStyle(ancestor);
1625
+ if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse" || Number(style.opacity) === 0)
1626
+ return false;
1627
+ }
1628
+ return true;
1629
+ }).map((node) => node.textContent).join("").replace(/\s+/gu, " ").trim();
1630
+ if (renderedName !== options.brandName)
1631
+ problems.push("The rendered product wordmark is not visible with its canonical display name.");
1632
+ }
1602
1633
  const box = header.getBoundingClientRect();
1603
1634
  if (box.left < -1 || box.right > view.innerWidth + 1)
1604
1635
  problems.push("The product header extends outside the viewport.");
@@ -1630,6 +1661,7 @@ function inspectMarketingHeader(options = {}, document = globalThis.document) {
1630
1661
  appearanceCount: appearances.length,
1631
1662
  brandHref,
1632
1663
  brandLabel,
1664
+ brandName,
1633
1665
  brandMark,
1634
1666
  links,
1635
1667
  problems
@@ -533,6 +533,7 @@ var marketingStyles = {
533
533
  $$css: true
534
534
  },
535
535
  header__brand: {
536
+ ksq1ai: "x6mezaz",
536
537
  k1xSpc: "x3nfvp2",
537
538
  kkeX5w: "x6s0dn4",
538
539
  kOIVth: "x1neeqzj",
@@ -659,6 +660,7 @@ var marketingStyles = {
659
660
  $$css: true
660
661
  },
661
662
  footer__name: {
663
+ ksq1ai: "x6mezaz",
662
664
  kVQacm: "xb3r6kr",
663
665
  kd00dl: "xlyipyv",
664
666
  kBYq9C: "xuxw1ft",
@@ -1844,6 +1846,7 @@ var marketingStyles = {
1844
1846
  $$css: true
1845
1847
  },
1846
1848
  related__card_name: {
1849
+ ksq1ai: "x6mezaz",
1847
1850
  kogj98: "x1ghz6dp",
1848
1851
  kMwMTN: "xtylnni",
1849
1852
  knIRL8: "xrtw95r",
package/dist/portfolio.js CHANGED
@@ -6,19 +6,19 @@ var portfolioSnapshot = {
6
6
  formatVersion: 1,
7
7
  provenance: {
8
8
  registry: "https://hraness.com/portfolio.json",
9
- commit: "d75ebaa21ae0576c1d6c71e1bea23c93b866601c",
10
- committedOn: "2026-09-30",
9
+ commit: "26b167cd5701caf2aec8ff15a0fd046d940bc6b5",
10
+ committedOn: "2026-10-05",
11
11
  upstreamContract: "hraness.portfolio-public/v1",
12
- upstreamDigest: "sha256:ba365e481a8b15c4a19503b1628e1b7ae9399e47055dde02bae124183a3e1447",
12
+ upstreamDigest: "sha256:0d3dd93744fc4adf183d81a4b62e4ba5bbca6dc417b6236fa99de7d19e6d7ecf",
13
13
  files: [{
14
14
  path: "portfolio.public.generated.json",
15
- sha256: "4c9e41dd1cb711d21a2da086de6b7d4adac2990ccda3909fa1cacf3b0ff44369"
15
+ sha256: "665c543651734bc2778c0bc50033cbb40e9604defbafbab83832e37af2a28e19"
16
16
  }, {
17
17
  path: "packages/brand-catalog/brands.yaml",
18
18
  sha256: "10f20e9d7b8ad0f108b56344c5d1b60cf3c54e6cec5e7024004b7b4f608f282c"
19
19
  }, {
20
20
  path: "brand-artwork.json",
21
- sha256: "7b1ba29f24352b33e666af059b8efbb273dd68269600b04d4d15ef4c94743876"
21
+ sha256: "ed55cc7bdfe2b3c897ce8742ed2809a0b7df9f90ac59192e1fe0c4a86bee7164"
22
22
  }, {
23
23
  path: "projects/hraness/public/marks/act60.svg",
24
24
  sha256: "b1e625903ac5deb8b9ac79469028122dd50d62cab36c433025a3976710723918"
@@ -28,6 +28,9 @@ var portfolioSnapshot = {
28
28
  }, {
29
29
  path: "projects/hraness/public/marks/algal.svg",
30
30
  sha256: "856ad5092fc3ac85863ba0ba079c8a2e1ecb195df06bd289a2602899244b4272"
31
+ }, {
32
+ path: "projects/hraness/public/marks/alt.svg",
33
+ sha256: "4544a61738e99296e072876b4807150bf7bfa57c5f4388cd9d3d646000a3ccd4"
31
34
  }, {
32
35
  path: "projects/hraness/public/marks/clankdar.svg",
33
36
  sha256: "12e321d88ec806e138b54ec2f00a605784486c26800d82c38c06a1ae0073efff"
@@ -58,6 +61,9 @@ var portfolioSnapshot = {
58
61
  }, {
59
62
  path: "projects/hraness/public/marks/message-like-me.svg",
60
63
  sha256: "5d30fa25c2f69d5dd1c4315189a3e9653be232baaf6cbf5cb4ce46b8dbcaab27"
64
+ }, {
65
+ path: "projects/hraness/public/marks/midiplace.svg",
66
+ sha256: "27ff03a1d987c9714d21b3e94033127154de0a1a70c4150446cc6ddee5ba8c8c"
61
67
  }, {
62
68
  path: "projects/hraness/public/marks/oh-computer.svg",
63
69
  sha256: "b9c62d7ef8168eae34a8cf388efb8d1ac9ec609a6d3d31b8e81af5c7a9f5724d"
@@ -100,6 +106,9 @@ var portfolioSnapshot = {
100
106
  }, {
101
107
  path: "projects/hraness/public/marks/system-one-skills.svg",
102
108
  sha256: "44855079c3dea26397d798926ec5689115e084ca26367b7ab73c7b0ea8b18119"
109
+ }, {
110
+ path: "projects/hraness/public/marks/textmock.svg",
111
+ sha256: "5780ba86aa03bf148a562bf40d50321d21df6df8d824ae902674abc2afd1fe05"
103
112
  }, {
104
113
  path: "projects/hraness/public/marks/valhalla.svg",
105
114
  sha256: "ae060052dc1550a4d377e3c4ebba9f2a5e5e58be1dafe8256a2a885063e84c24"
@@ -145,7 +154,7 @@ var portfolioSnapshot = {
145
154
  "home-live": "Keep the recent work in view.",
146
155
  "home-file-copy": "Try a smaller copy. Keep a way back.",
147
156
  "home-results": "38% smaller on requests it compacted.",
148
- "home-film": "Watch it in 75 seconds.",
157
+ "home-film": "Watch it in 34 seconds.",
149
158
  "home-install": "Start with one session.",
150
159
  "home-questions": "Before you install.",
151
160
  "home-related": "Other tools from our studio",
@@ -186,7 +195,7 @@ var portfolioSnapshot = {
186
195
  long: "Excalibur (xcb) is a terminal and router for developers who pay for more than one coding agent. Type the work into one conversation, and xcb sends each task to a Claude, Codex, or Devin account that is signed in, idle, and not at a known usage limit, on a model that fits the job. Tasks keep running after you close the terminal, every session appears on one screen, and each account runs one task at a time. Other agents can hand xcb work with one JSON command. xcb is free and MIT licensed, with releases for macOS and Linux.",
187
196
  hero: {
188
197
  heading: "Use your Claude, Codex, and Devin plans from one agent.",
189
- summary: "Excalibur (xcb) is for developers who pay for more than one coding agent. Each task runs in Claude Code, Codex, or the Devin CLI on an account that is signed in, idle, and not at a known limit. Use its terminal or your own agent or app.",
198
+ summary: "Use the AI plans you already pay for. xcb routes each task to an available account, from your terminal or app.",
190
199
  primaryAction: "Install xcb",
191
200
  secondaryAction: "See how it works"
192
201
  },
@@ -575,30 +584,29 @@ var portfolioSnapshot = {
575
584
  canonicalUrl: "https://textbutler.app",
576
585
  status: "active",
577
586
  copyStatus: "proposed",
578
- aliases: ["Message Like Me"],
587
+ aliases: [],
579
588
  mark: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 590 588' width='590' height='588'%3E%3Cpath d='M0 0 C3.7021 0.9255 6.4331 2.1039 9.8203 3.8086 C33.3452 15.4968 57.4529 25.6075 82.8125 32.625 C86.8765 33.9594 89.1312 34.8704 92 38 C94.1691 42.578 95.597 47.0155 96.75 51.9375 C105.3381 84.8912 129.1005 113.746 158.0735 131.0774 C177.2853 142.2466 197.9348 149.8729 220 153 C221.3651 153.1953 221.3651 153.1953 222.7578 153.3945 C260.3492 157.7055 302.6036 147.646 332.6899 124.0808 C335.2718 121.9568 337.7934 119.7763 340.2803 117.542 C341.9152 116.076 343.5857 114.65 345.2578 113.2266 C362.5093 98.1812 375.0458 78.2509 381.7461 56.4062 C382.0482 55.4221 382.3503 54.438 382.6616 53.4241 C383.2507 51.4713 383.8233 49.5135 384.3774 47.5505 C385.9755 42.1672 387.2446 38.3557 392 35 C395.584 33.3897 399.2571 32.186 403 31 C404.083 30.6466 405.1659 30.2933 406.2817 29.9292 C408.6243 29.1663 410.9682 28.4075 413.3132 27.6523 C433.7067 21.0444 453.5375 13.4298 472.3054 2.9961 C477.7181 0 477.7181 0 481 0 C481.0467 12.693 481.082 25.3859 481.1036 38.0789 C481.114 43.9748 481.128 49.8707 481.1509 55.7666 C481.1729 61.4725 481.1846 67.1783 481.1898 72.8843 C481.1934 75.0448 481.2005 77.2053 481.2115 79.3658 C481.412 120.7375 472.888 158.7884 447 192 C446.3194 192.9023 445.6388 193.8047 444.9375 194.7344 C416.3304 231.3601 374.5581 253.3259 329 260 C320.2884 261.0318 311.6364 261.154 302.8718 261.1611 C301.3938 261.1661 299.9157 261.1711 298.3928 261.1762 C294.3653 261.1892 290.3377 261.1957 286.3102 261.2002 C283.7817 261.2031 281.2532 261.2072 278.7248 261.2117 C270.7787 261.2253 262.8327 261.235 254.8867 261.2389 C245.7802 261.2434 236.6739 261.2609 227.5675 261.2899 C220.4859 261.3117 213.4043 261.3216 206.3227 261.3229 C202.1135 261.324 197.9044 261.3296 193.6952 261.3478 C163.0583 261.472 136.0157 258.5483 107.2949 247.679 C106.4164 247.3466 105.5379 247.0143 104.6328 246.6719 C103.8582 246.3738 103.0837 246.0757 102.2856 245.7686 C97.5982 244.1082 97.5982 244.1082 92.8005 244.7058 C92.0504 245.0955 91.3002 245.4852 90.5273 245.8867 C89.6464 246.3248 88.7654 246.7628 87.8577 247.2141 C86.894 247.7003 85.9304 248.1865 84.9375 248.6875 C61.3112 260.0322 35.6255 267.7281 10 273 C8.7867 273.2523 8.7867 273.2523 7.5488 273.5098 C-4.0855 275.8955 -15.1202 277.1809 -27 277 C-25.3641 273.7281 -24.3294 272.1014 -21.9375 269.5625 C2.4619 242.1765 15.288 203.3126 13.875 166.75 C13.0762 157.4147 10.4775 148.7963 7.7305 139.8789 C2.7207 123.3966 -0.1826 106.9524 -0.1135 89.6851 C-0.1137 88.7082 -0.1138 87.7314 -0.114 86.725 C-0.1133 83.5328 -0.1055 80.3406 -0.0977 77.1484 C-0.0958 74.9207 -0.0944 72.693 -0.0934 70.4652 C-0.0896 64.6292 -0.0798 58.7932 -0.0687 52.9572 C-0.0584 46.991 -0.0539 41.0248 -0.0488 35.0586 C-0.0381 23.3724 -0.0211 11.6862 0 0 Z ' transform='translate%2868,270%29' fill='%232474d4'/%3E%3Cpath d='M0 0 C6.8496 0.0001 13.699 -0.0137 20.5486 -0.0308 C25.91 -0.042 31.2714 -0.0439 36.6329 -0.0434 C39.1574 -0.0446 41.6819 -0.0489 44.2064 -0.0567 C63.3887 -0.1108 82.8493 0.0066 101.6213 4.4353 C102.5676 4.6515 103.5138 4.8676 104.4888 5.0903 C119.6158 8.6599 133.1818 13.7911 146.8713 21.1853 C147.5444 21.54 148.2174 21.8946 148.9109 22.26 C162.6556 29.509 174.5849 38.5065 185.8713 49.1853 C186.6925 49.9536 187.5136 50.7219 188.3596 51.5134 C220.1762 82.1919 235.9745 125.1447 237.4338 168.6853 C237.477 169.8893 237.5202 171.0933 237.5647 172.3337 C237.6701 175.2842 237.7722 178.2347 237.8713 181.1853 C177.1878 214.3549 177.1878 214.3549 158.8323 210.5564 C151.6117 207.9496 146.6734 204.9021 142.6995 198.2126 C140.0778 192.4954 139.0856 186.4481 137.9338 180.3103 C134.2729 160.8391 124.8987 144.1095 108.5588 132.4353 C95.1947 123.6496 79.3058 116.1065 63.0003 116.0381 C61.8247 116.031 60.649 116.0238 59.4377 116.0164 C58.1561 116.0138 56.8746 116.0111 55.5542 116.0083 C53.519 115.9984 53.519 115.9984 51.4426 115.9884 C46.9462 115.9687 42.4498 115.957 37.9534 115.947 C36.3982 115.943 34.8431 115.9389 33.288 115.9347 C25.9709 115.9156 18.6539 115.9014 11.3368 115.8931 C2.9325 115.8833 -5.4714 115.8571 -13.8755 115.8166 C-20.3956 115.7862 -26.9156 115.7716 -33.4357 115.7683 C-37.3175 115.7659 -41.1989 115.7572 -45.0805 115.7318 C-74.4696 115.5658 -100.5287 118.1185 -122.9412 139.3728 C-135.7309 152.8595 -143.2102 169.5004 -146.0037 187.7478 C-147.1841 194.3582 -149.109 200.4944 -154.2458 205.072 C-161.4566 210.0856 -168.2706 212.294 -177.1287 211.1853 C-194.7966 206.8473 -211.4584 197.5573 -227.7537 189.7478 C-229.0416 189.1324 -230.3295 188.5169 -231.6565 187.8828 C-232.8565 187.3033 -234.0564 186.7238 -235.2927 186.1267 C-236.3699 185.6079 -237.4471 185.0892 -238.5569 184.5547 C-241.1287 183.1853 -241.1287 183.1853 -243.1287 181.1853 C-243.5975 177.6056 -243.4606 173.9795 -243.4412 170.3728 C-243.4355 169.2935 -243.4299 168.2141 -243.4241 167.1021 C-242.7275 120.0562 -221.4831 78.9885 -188.5093 46.136 C-158.1217 16.7697 -115.7152 1.8102 -73.9607 0.6345 C-73.231 0.6137 -72.5012 0.5929 -71.7494 0.5714 C-47.8402 -0.0871 -23.9161 -0.0019 0 0 Z ' transform='translate%28311.128662109375,40.814697265625%29' fill='%232474d4'/%3E%3Cpath d='M0 0 C0.8909 0.1924 1.7818 0.3848 2.6997 0.583 C5.9365 1.335 9.1574 2.1376 12.3765 2.9619 C21.6086 5.3006 30.8581 7.0572 40.2773 8.4609 C41.3569 8.6238 42.4364 8.7867 43.5486 8.9546 C57.6085 10.9603 71.6517 11.4188 85.8398 11.3984 C86.6237 11.3978 87.4076 11.3972 88.2152 11.3966 C114.4849 11.342 140.4586 9.1714 165.5789 1.0537 C170.2085 -0.3972 173.6011 -1.2844 178.4023 0.2109 C181.6798 3.0571 182.3517 4.5985 182.7109 8.9453 C181.6692 23.3449 168.4745 36.5795 158.5898 45.9609 C136.4483 65.0292 107.503 74.7578 78.4023 73.2109 C50.8408 70.8727 27.0272 60.8078 7.4023 41.2109 C6.5889 40.4091 5.7755 39.6073 4.9375 38.7812 C-2.2872 31.2478 -10.9632 19.8732 -11.9727 9.2734 C-11.5585 4.7868 -10.8308 3.2593 -7.5977 0.2109 C-4.3471 -0.8726 -3.2573 -0.7085 0 0 Z ' transform='translate%28222.59765625,310.7890625%29' fill='%232474d4'/%3E%3Cpath d='M0 0 C8.176 4.7656 13.9158 12.0195 16.9375 21 C19.2756 30.367 18.3166 38.3415 14 47 C8.5855 55.3913 1.5736 62.0972 -8.3633 64.5938 C-19.6329 66.3301 -28.7001 64.7079 -38.1875 58.4375 C-45.0857 52.9105 -49.7749 44.7121 -51 36 C-51.9467 24.3944 -49.4287 15.7487 -42.3164 6.4883 C-31.427 -5.2091 -13.8754 -7.7489 0 0 Z ' transform='translate%28263,204%29' fill='%232474d4'/%3E%3Cpath d='M0 0 C6.2372 4.9898 10.0487 11.8918 12.75 19.3125 C14.0462 31.4216 12.944 41.3809 5.25 51.0625 C-1.0317 57.7095 -9.4841 61.7212 -18.5742 62.5156 C-30.0556 62.7434 -37.861 59.2704 -46.1602 51.5312 C-52.6985 44.7569 -55.406 37.1682 -55.75 27.8125 C-55.37 17.4666 -51.6937 8.5864 -44.25 1.3125 C-30.4055 -9.0597 -14.3198 -9.718 0 0 Z ' transform='translate%28391.25,206.6875%29' fill='%232474d4'/%3E%3C/svg%3E",
580
589
  messaging: {
581
590
  formatVersion: 1,
582
591
  product: "textbutler",
583
592
  names: {
584
593
  name: "TextButler",
585
- command: "textbutler",
586
- formerly: ["Message Like Me"]
594
+ command: "textbutler"
587
595
  },
588
596
  category: "Messaging assistant for Mac",
589
597
  tagline: "An AI butler in your messaging apps.",
590
598
  short: "AI butler for the iMessage, WhatsApp, and Beeper chats you choose",
591
- meta: "TextButler is an AI butler for the iMessage, WhatsApp, and Beeper chats you choose. It runs on your Mac and answers as a clearly marked assistant.",
592
- medium: "TextButler is an AI butler for the iMessage, WhatsApp, and Beeper chats you choose on your Mac. Turn it on for one person, and it replies as a clearly marked assistant that knows your history with them.",
593
- long: "TextButler is an AI butler for your messages, running on your Mac. Turn it on for the chats you choose in iMessage, WhatsApp, or Beeper, and it replies as a clearly marked assistant that keeps notes on each person in files you can edit. New installs start paused and every contact starts off. Choose a local model, your Gateway key, or a connected subscription; local-model replies are in testing. Hosted AI providers receive the context needed to write a reply. TextButler is free and MIT licensed.",
599
+ meta: "TextButler is an AI butler for the iMessage, WhatsApp, and Beeper chats you choose. It runs on your Mac with the model or AI subscription you select.",
600
+ medium: "TextButler is an AI butler for the iMessage, WhatsApp, and Beeper chats you choose on your Mac. Turn it on for a conversation to draft or send replies using your shared history.",
601
+ long: "TextButler is an AI butler for your messages, running on your Mac. Turn it on for the chats you choose in iMessage, WhatsApp, or Beeper. It uses conversation history and notes on each person in files you can edit. New installs start paused. Choose a local model, your Gateway key, or a connected subscription. Reply labels are on by default and configurable per person. Hosted AI providers receive the context needed to write a reply; optional web search uses a Gateway key. TextButler is free and MIT licensed.",
594
602
  hero: {
595
603
  heading: "An AI butler in your messaging apps.",
596
- summary: "A clearly marked AI assistant answers the people you choose, from your Mac.",
604
+ summary: "An AI assistant answers the chats you choose, from your Mac.",
597
605
  primaryAction: "Have your agent set it up",
598
606
  secondaryAction: "See how it works"
599
607
  },
600
608
  headings: {
601
- "how-title": "From “butler” to a marked reply.",
609
+ "how-title": "From a message to a reply.",
602
610
  "supports-title": "What it works with",
603
611
  "models-title": "Pick what writes replies",
604
612
  "setup-title": "Your agent sets it up. You stay in charge.",
@@ -614,7 +622,7 @@ var portfolioSnapshot = {
614
622
  "prefer-to-do-it-yourself": "Prefer to do it yourself?",
615
623
  "your-agent-speaks-its-language": "Your agent speaks its language",
616
624
  "it-s-there-when-you-aren-t": "It’s there when you aren’t.",
617
- "it-never-pretends-to-be-you": "It never pretends to be you.",
625
+ "it-never-pretends-to-be-you": "Choose how replies are marked.",
618
626
  "it-runs-on-your-mac": "It runs on your Mac.",
619
627
  "site-title": "TextButler: an AI butler for iMessage and WhatsApp on Mac",
620
628
  "home-writer-local": "A local model on your Mac",
@@ -625,7 +633,7 @@ var portfolioSnapshot = {
625
633
  "home-flow-indicator": "\uD83D\uDC40, right away.",
626
634
  "home-flow-context": "It reads the room.",
627
635
  "home-flow-model": "Your chosen model writes the reply.",
628
- "home-flow-send": "Marked, then sent.",
636
+ "home-flow-send": "Reply in the same chat.",
629
637
  "home-flow-step-in": "You can step in anytime.",
630
638
  "home-setup-agent": "Ask your agent.",
631
639
  "home-setup-mac": "Say yes to your Mac.",
@@ -636,7 +644,7 @@ var portfolioSnapshot = {
636
644
  status: {
637
645
  default: "proposed"
638
646
  },
639
- reviewedOn: "2026-09-29"
647
+ reviewedOn: "2026-10-01"
640
648
  }
641
649
  },
642
650
  wrench: {
@@ -729,14 +737,14 @@ var portfolioSnapshot = {
729
737
  formerly: ["Ensoul"]
730
738
  },
731
739
  category: "People research for agents",
732
- tagline: "See how someone thinks, and where every claim comes from.",
740
+ tagline: "Learn everything about anyone based on their internet presence",
733
741
  short: "Free agent skill that writes dated dossiers on people, sources cited",
734
742
  meta: "Soulscrape is a free agent skill that writes a dated dossier on a person, with every claim tied to its sources, kept private or published.",
735
743
  medium: "Soulscrape is a free agent skill that writes a dated dossier on how a person decides, writes, argues, and changes their mind, with every claim tied to its sources. Keep it private, or publish it.",
736
744
  long: "Soulscrape is a free, MIT-licensed agent skill that turns sources you're allowed to use into a dated dossier on one person: how they decide, write, argue, and change their mind. It runs inside Claude Code, Codex, or another agent that loads skills, with your own model and tools, and needs no Soulscrape account. Facts, stated beliefs, patterns, and speculation stay apart, and the dossier lists what the record cannot settle. Keep it private, or publish it with a free Hraness account as a web page, a JSON packet, and a Markdown copy anyone can cite.",
737
745
  hero: {
738
- heading: "See how someone thinks, and where every claim comes from.",
739
- summary: "Turn sources into a dated dossier, with evidence behind every claim.",
746
+ heading: "Learn everything about anyone based on their internet presence",
747
+ summary: "Turn their writing, talks, and posts into a detailed dossier, with sources for every claim.",
740
748
  primaryAction: "Install the skill",
741
749
  secondaryAction: "Browse the dossiers"
742
750
  },
@@ -745,8 +753,8 @@ var portfolioSnapshot = {
745
753
  "examples-title": "Explore a finished dossier",
746
754
  "method-title": "Read the claims alongside their evidence",
747
755
  "use-cases-title": "Use the research in your own work",
748
- "install-title": "Install and write your first dossier",
749
- "indexes-title": "Publish when you are ready",
756
+ "install-title": "Ask your agent to set it up",
757
+ "indexes-title": "Publish your dossier",
750
758
  "boundaries-title": "Keep the research within its limits",
751
759
  "questions-title": "Questions",
752
760
  "related-title": "Other tools from our studio",
@@ -770,7 +778,7 @@ var portfolioSnapshot = {
770
778
  status: {
771
779
  default: "proposed"
772
780
  },
773
- reviewedOn: "2026-09-24"
781
+ reviewedOn: "2026-09-30"
774
782
  }
775
783
  },
776
784
  iconplace: {
@@ -1271,7 +1279,7 @@ var portfolioSnapshot = {
1271
1279
  long: "Act 60 promises large Puerto Rico tax savings, but fees, yearly costs, and the federal residency rules decide the real number. act60.me models the move before you make it: a calculator that itemizes one-time and annual costs beside its assumptions, guides that cite the official sources and the date each was checked, and a private day tracker for the presence tests a calendar can measure. Investor applications filed in 2026 face a December 31 deadline; the guides say which rules changed and which still apply.",
1272
1280
  hero: {
1273
1281
  heading: "Puerto Rico Act 60 calculator",
1274
- summary: "Estimate Act 60 savings from the export-services benefit (formerly Act 20) and the investor benefit (formerly Act 22) after fees, the investor donation, and yearly costs. Rates and source dates sit beside the result. No account needed.",
1282
+ summary: "Estimate your Act 60 savings after fees and yearly costs. No account required.",
1275
1283
  primaryAction: "Estimate your savings",
1276
1284
  secondaryAction: "Choose your guide"
1277
1285
  },
@@ -1496,6 +1504,101 @@ var portfolioSnapshot = {
1496
1504
  reviewedOn: "2026-09-24"
1497
1505
  }
1498
1506
  },
1507
+ textmock: {
1508
+ id: "textmock",
1509
+ name: "Textmock",
1510
+ oneLiner: "Fictional text message screenshots and animations, made in your browser",
1511
+ brandDescription: null,
1512
+ canonicalUrl: "https://textmock.com",
1513
+ status: "active",
1514
+ copyStatus: "proposed",
1515
+ aliases: [],
1516
+ mark: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='32' height='32'%3E%3Cpath fill='%232474d4' fill-rule='evenodd' d='M7 3h18a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H13l-7 7v-7H7a5 5 0 0 1-5-5V8a5 5 0 0 1 5-5Zm3 8a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm6 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm6 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z'/%3E%3C/svg%3E",
1517
+ messaging: {
1518
+ formatVersion: 1,
1519
+ product: "textmock",
1520
+ names: {
1521
+ name: "Textmock"
1522
+ },
1523
+ category: "Text message mockup studio",
1524
+ tagline: "Create text message screenshots and animations in your browser.",
1525
+ short: "Fictional text message screenshots and animations, made in your browser",
1526
+ meta: "Textmock lets you make fictional text message screenshots and animations in your browser, in iMessage, WhatsApp, Telegram, and Instagram styles.",
1527
+ medium: "Textmock lets you make fictional text message screenshots and animations in your browser. Write the conversation, time each message, and export a PNG, GIF, or MP4, or share a link someone can open and edit.",
1528
+ long: "Textmock is a browser studio for fictional text conversations in stories, demos, and designs. Write the messages and choose who sends each one, then add reactions, read receipts, photos, and video clips. Set when each message appears, play the exchange back, and export a PNG screenshot, a looping GIF, or a silent MP4 that your browser renders on your device. Your draft stays in your browser; download a backup or share a scene link someone can open and make their own. Free exports use the iMessage style and carry a small Textmock signature. Pro removes it and adds Instagram, WhatsApp, and Telegram styles. Textmock does not send messages.",
1529
+ hero: {
1530
+ heading: "Say it in a conversation.",
1531
+ summary: "A joke for your group chat, a moment in your story, or a product demo that feels like real life. Make it in a few taps, right in your browser.",
1532
+ primaryAction: "Make a conversation",
1533
+ secondaryAction: "Read the introduction"
1534
+ },
1535
+ status: {
1536
+ default: "proposed"
1537
+ }
1538
+ }
1539
+ },
1540
+ midiplace: {
1541
+ id: "midiplace",
1542
+ name: "midi.place",
1543
+ oneLiner: "Research lab for content-addressed MIDI ideas and variations",
1544
+ brandDescription: null,
1545
+ canonicalUrl: "https://midi.place",
1546
+ status: "active",
1547
+ copyStatus: "proposed",
1548
+ aliases: [],
1549
+ mark: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='32' height='32'%3E%3Cpath fill='%232474d4' fill-rule='evenodd' d='M7 21a5 5 0 1 0 0 10 5 5 0 0 0 0-10Zm13-5a5 5 0 1 0 0 10 5 5 0 0 0 0-10ZM11 4h15v6H14v13h-3V4Zm13 6v8h-3V10h3Z'/%3E%3C/svg%3E",
1550
+ messaging: {
1551
+ formatVersion: 1,
1552
+ product: "midiplace",
1553
+ names: {
1554
+ name: "midi.place"
1555
+ },
1556
+ category: "MIDI research lab",
1557
+ tagline: "Compare MIDI ideas and their variations.",
1558
+ short: "Research lab for content-addressed MIDI ideas and variations",
1559
+ meta: "midi.place is a research lab for content-addressed MIDI ideas: original loops, controlled variations, and replayable generation receipts.",
1560
+ medium: "midi.place is a research lab for content-addressed MIDI ideas. It compares original loops with controlled variations, keeps a replayable receipt for every generation, and renders audio with Soundfish. The public site is not live yet.",
1561
+ hero: {
1562
+ heading: "Compare MIDI ideas and their variations.",
1563
+ summary: "midi.place is a research lab for content-addressed MIDI ideas: original loops, controlled variations, and replayable generation receipts.",
1564
+ primaryAction: "Open midi.place"
1565
+ },
1566
+ status: {
1567
+ default: "proposed"
1568
+ }
1569
+ }
1570
+ },
1571
+ alt: {
1572
+ id: "alt",
1573
+ name: "Alt",
1574
+ oneLiner: "Personal canvas with an on-device model and replayable plans",
1575
+ brandDescription: null,
1576
+ canonicalUrl: "https://alt.dog",
1577
+ status: "active",
1578
+ copyStatus: "proposed",
1579
+ aliases: [],
1580
+ mark: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='32' height='32'%3E%3Cpath fill='%232474d4' fill-rule='evenodd' d='M4 17C4 8 8 3 16 3s13 5 13 13v13H16C8 29 4 25 4 17Zm6 1c0-5 2-8 6-8s6 3 6 8v4h-4v-3c-1 3-8 4-8-1Zm4-1c0 3 4 2 4-1s-4-3-4 1Z'/%3E%3C/svg%3E",
1581
+ messaging: {
1582
+ formatVersion: 1,
1583
+ product: "alt",
1584
+ names: {
1585
+ name: "Alt"
1586
+ },
1587
+ category: "Personal canvas",
1588
+ tagline: "A canvas for questions, drawings, and small tools.",
1589
+ short: "Personal canvas with an on-device model and replayable plans",
1590
+ meta: "Alt is a canvas for questions, drawings, and small tools, with a model that runs on your device and optional encrypted sync.",
1591
+ medium: "Alt is a personal workspace you can reshape with a local model. It keeps an editable plan with replayable history, and your plans, reading, tools, and conversations stay on your device, with optional encrypted sync.",
1592
+ hero: {
1593
+ heading: "A canvas for questions, drawings, and small tools.",
1594
+ summary: "Alt is a canvas for questions, drawings, and small tools, with a model that runs on your device and optional encrypted sync.",
1595
+ primaryAction: "Open Alt"
1596
+ },
1597
+ status: {
1598
+ default: "proposed"
1599
+ }
1600
+ }
1601
+ },
1499
1602
  "pattern-language": {
1500
1603
  id: "pattern-language",
1501
1604
  name: "Pattern Language",
@@ -1621,12 +1724,12 @@ var portfolioSnapshot = {
1621
1724
  slug: "knowledge",
1622
1725
  title: "Knowledge",
1623
1726
  tone: "indigo",
1624
- members: ["kb", "oh-computer", "sponge", "sloptrade", "roughday"]
1727
+ members: ["kb", "oh-computer", "sponge", "sloptrade", "roughday", "alt"]
1625
1728
  }, {
1626
1729
  slug: "media",
1627
1730
  title: "Media",
1628
1731
  tone: "amber",
1629
- members: ["iconplace", "slopcamera", "soundfish"]
1732
+ members: ["iconplace", "slopcamera", "soundfish", "textmock", "midiplace"]
1630
1733
  }, {
1631
1734
  slug: "token-maximalists",
1632
1735
  title: "Tools for Token Maximalists",
@@ -1696,7 +1799,15 @@ var portfolioSnapshot = {
1696
1799
  kind: "contract",
1697
1800
  direction: "shared",
1698
1801
  label: "shared bundle format",
1699
- detail: "Both tools implement the versioned message-like-me.local-message-bundle interchange without importing each other's private state."
1802
+ detail: "Both tools read and write the same versioned TextButler local message bundle format without importing each other's private state."
1803
+ }, {
1804
+ id: "runtime:gobstopper:aicharts:installs",
1805
+ source: "gobstopper",
1806
+ target: "aicharts",
1807
+ kind: "runtime",
1808
+ direction: "forward",
1809
+ label: "installs",
1810
+ detail: "The Gobstopper installer adds aicharts and turns on its local usage history, which stays on your computer and never uploads."
1700
1811
  }, {
1701
1812
  id: "runtime:gobstopper:xcb:compacts-sessions-for",
1702
1813
  source: "gobstopper",
@@ -1706,13 +1817,13 @@ var portfolioSnapshot = {
1706
1817
  label: "compacts sessions for",
1707
1818
  detail: "Excalibur (xcb) uses Gobstopper's elision policy to drop stale tool output from Claude Code and Codex prompts once context passes a threshold, and keeps the original output in local history. It is on by default."
1708
1819
  }, {
1709
- id: "contract:xcb:aicharts:exports-sessions-for",
1820
+ id: "runtime:xcb:aicharts:installs",
1710
1821
  source: "xcb",
1711
1822
  target: "aicharts",
1712
- kind: "contract",
1823
+ kind: "runtime",
1713
1824
  direction: "forward",
1714
- label: "exports sessions for",
1715
- detail: "Excalibur (xcb) measures subscription usage locally and, when you turn on exports, writes session files in the aicharts format. Automatic upload is not available."
1825
+ label: "installs",
1826
+ detail: "The Excalibur (xcb) installer adds aicharts and turns on its local usage history, which stays on your computer. With exports on, xcb also writes session files in the aicharts format; automatic upload is not available."
1716
1827
  }, {
1717
1828
  id: "contract:soulscrape:peopleblade:exports-dossier-packets",
1718
1829
  source: "soulscrape",
@@ -1922,7 +2033,7 @@ var portfolioSnapshot = {
1922
2033
  label: "records drawing runs with",
1923
2034
  detail: "The icon.place drawing lab runs each experiment as an ALGAL program in the browser and records the proposal, candidates, and selection as receipts it can replay; the live site does not use ALGAL yet."
1924
2035
  }],
1925
- digest: "sha256:1af50f624f0d06ec13e1531564a8066795ae3fed732210b6f642179730100103"
2036
+ digest: "sha256:4cc6210bb3827828fd7f75b0c9a1b8182acbcf098071c5db8855bf4a8a0a8e5e"
1926
2037
  };
1927
2038
 
1928
2039
  // src/portfolio.ts