diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 611b0b4..2275483 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -94,6 +94,8 @@ jobs: - run: npm run build + - run: node --experimental-strip-types --test src/data/navigation.test.mjs + - run: npm run check:presentations - run: node --experimental-strip-types --test src/data/mind-nervous-system-body-slides.test.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index c5281f9..beeece1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. Format follows [Keep a Changelog](https://keepachangelog.com/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.19.0] - 2026-07-26 + +### Added + +- Reusable Astro design-system foundations: named layout and typography roles plus shared section-intro, destination-card, structured-card, closing-band, and terminal patterns. +- A guided three-session Devague capture story with accessible transcript evidence, human-gate previews, and a reshaped pipeline reference. +- Focused regression coverage for navigation and presentations, with Devague story anchors validated when the site builds. + +### Changed + +- Unified the site header, primary navigation, grouped footer, agent directory, and library destinations, including a sticky header and clearer internal and external link treatments. +- Migrated the four agent profiles and current library, article, and presentation surfaces onto reusable patterns while preserving their bespoke compositions. +- Consolidated the UX review into current spec, plan, and delivery records; removed generated review snapshots and superseded decision material; automatic future-page adoption remains deferred. + +### Fixed + +- Improved diagram spacing, agent-page code and terminal treatments, destination clarity, and presentation contract coverage across responsive layouts. + ## [0.18.2] - 2026-07-22 ### Changed diff --git a/README.md b/README.md index 6404455..ced0014 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,13 @@ provisioned Cloudflare state and the DNS cutover procedure are recorded in [`docs/deploy-runbook.md`](docs/deploy-runbook.md). DNS for AgentCulture.org is operator-owned, so cutover is coordinated, not self-serve. +The adopted navigation, design-system, agent-page, and Devague decisions are +summarized in the +[`site-ux-review` delivery record](docs/deliveries/2026-07-21-site-ux-review.md). +Use that record and the implementation as the current source of truth; the +Astro build plus focused navigation and presentation tests provide regression +coverage. + Two things worth knowing if you're extending it: the sibling repos' `publish.yml` are all **PyPI** workflows, not deploy templates — this repo's deploy workflow was written fresh, in the filename slot the removed diff --git a/docs/deliveries/2026-07-21-site-ux-review.md b/docs/deliveries/2026-07-21-site-ux-review.md new file mode 100644 index 0000000..fe9978c --- /dev/null +++ b/docs/deliveries/2026-07-21-site-ux-review.md @@ -0,0 +1,69 @@ +# Delivery Summary — site-ux-review + +plan: `site-ux-review` · run: `complete` · date: `2026-07-26` · draft PR: +[#30](https://github.com/agentculture/org/pull/30) + +## Intent + +Turn a measured review of the original site into reusable foundations +for the current twelve-route Astro build. Preserve the site's visual identity +and bespoke page compositions while making navigation, wayfinding, destination +cues, long-form openings, information cards, terminal treatments, and Devague +evidence easier to understand and maintain. + +## Actual Delivery + +| Plan task | Status | What landed | +|---|---|---| +| `t1` shared system | delivered | Named type, leading, tracking, rail, measure, diagram-spacing, and sticky-header roles with explicit container ownership. | +| `t2` navigation and destinations | delivered | Typed grouped header, grouped sitemap footer, stable agent groups, capped Library features, external Learn product, whole-card destinations, and safe external cues. | +| `t3` agent-page patterns | delivered | Shared `SectionIntro`, `StructuredCard`, `DestinationCard`, `ClosingBand`, and inline-code treatments; aligned terminal and diagram rules; bespoke compositions retained. | +| `t4` Devague | delivered | Three guided sessions, fourteen source-anchored excerpts, accessible full transcripts, read-only gate previews, repaired flow sequence, and a ruled seven-stage pipeline reference. | +| `t5` reconciliation | delivered | Breadcrumbs/local navigation experiments removed, focused navigation and presentation coverage retained, version advanced to `0.19.0`, and review artifacts consolidated into this record set. | + +## Final Decisions + +| Direction | Final status | Reason | +|---|---|---| +| Typed grouped navigation and sitemap footer | adopted | Keeps route ownership, current states, featured coverage, and Learn's external ownership explicit. | +| Whole-card destination links with visible kind | adopted | Resolves the directory's target-size and destination-ambiguity findings together. | +| Shared semantic components | adopted | Reduces repeated presentation decisions without forcing unrelated content into one visual primitive. | +| Guided Devague sessions and transcript modal | adopted | Teaches the evidence while preserving complete, verbatim captures. | +| Ruled pipeline reference list | adopted | Keeps the animated flow primary and makes the stage detail quieter lookup material. | +| Directory filter and sticky jump list | superseded | Stable group fragments and grouped navigation provide the accepted wayfinding without another control surface. | +| Generic `AgentPage` and `Terminal` components | deferred | The four pages share design rules but still have meaningfully different structures and terminal contracts. | +| Breadcrumbs and local contents navigation | deferred | They were removed from this PR pending a separate information-architecture decision. | +| Automatic adoption by future pages | deferred | New pages must choose semantic components deliberately. | +| Generated review pages and static snapshots | retired | Source and these records now contain the accepted decisions. | + +## Evidence + +- Astro production build: twelve static routes +- navigation: six focused behavior tests +- delivered inventory: 28 authored section-introduction calls render 35 + openings; 12 structured-card calls render 70 cards +- Devague build input: three sessions and fourteen source-anchored excerpts +- presentations: 23 built-page checks and 20 slide-data tests +- Python test, coverage, formatting, lint, security, Markdown, local-link, and + strict repository-doctor lanes pass on the final branch + +## Source of Truth + +The implementation is authoritative for current behavior. The Astro build, +focused navigation tests, and retained presentation tests cover durable +regressions; this delivery records the final PR state. The matching +[spec](../specs/2026-07-21-site-ux-review.md) preserves accepted requirements, +and the [plan](../plans/2026-07-21-site-ux-review.md) preserves the delivery +sequence. + +Focused records cover the shared +[section introduction](2026-07-23-global-section-opener.md) and +[structured card](2026-07-23-global-structured-card.md) patterns. + +## Remaining Work + +- complete manual visual and keyboard review on the draft deploy preview +- decide breadcrumbs/local contents navigation separately +- consider broader agent-page or terminal abstraction only when another page + provides enough evidence for a stable interface +- keep Learn source and deployment in its owning project diff --git a/docs/deliveries/2026-07-23-global-section-opener.md b/docs/deliveries/2026-07-23-global-section-opener.md new file mode 100644 index 0000000..46f60a4 --- /dev/null +++ b/docs/deliveries/2026-07-23-global-section-opener.md @@ -0,0 +1,45 @@ +# Delivery Summary — global-section-opener + +plan: `global-section-opener` · run: `complete` · date: `2026-07-26` · draft +PR: [#30](https://github.com/agentculture/org/pull/30) + +## Intent + +Give long-form sections one accessible, readable opening grammar while +preserving the article's definitions and every page's bespoke downstream +composition. + +## Actual Delivery + +| Plan task | Status | What landed | +|---|---|---| +| `t1` shared component | delivered | `SectionIntro.astro` owns eyebrow, stable heading, optional post-title content, readable measures, title spacing, and reveal behavior. | +| `t2` agent profiles | delivered | Devague 6, Colleague 9, Lobes 5, and Reachy Mini CLI 7 authored calls; parent sections use matching `aria-labelledby` IDs. | +| `t3` article | delivered | One loop-authored call renders eight beat openings while definitions, lede styling, paragraph reveals, and evidence notes remain local. | +| `t4` validation | delivered | The production build and focused semantic/visual review covered ordering, measures, accessible labels, reveal behavior, and the presentation exclusion. | + +## Final Decisions + +- Agent sections use grouped introductory reveals; the article retains + paragraph-level reveals. +- The article's definitions use the named `after-title` slot rather than moving + into the shared component's data model. +- Agent headings use standard title spacing; the article keeps its relaxed + variant. +- Explicit template branches prevent absent reveal flags from becoming literal + false-valued data attributes. +- The presentation remains a separate slide pattern. + +## Evidence + +- delivery snapshot: 28 authored component calls render 35 section openings +- all five migrated routes retain stable heading IDs and labelled parent regions +- article heading → definitions → prose order is preserved in built output +- the seven-slide presentation renders no shared section-introduction markers +- the Astro production build passes + +## Boundaries + +- no copy, section order, route, breadcrumb, local-navigation, Learn, or + deployment change belongs to this component +- future pages must opt into the component deliberately diff --git a/docs/deliveries/2026-07-23-global-structured-card.md b/docs/deliveries/2026-07-23-global-structured-card.md new file mode 100644 index 0000000..c81c6d6 --- /dev/null +++ b/docs/deliveries/2026-07-23-global-structured-card.md @@ -0,0 +1,48 @@ +# Delivery Summary — global-structured-card + +plan: `global-structured-card` · run: `complete` · date: `2026-07-26` · draft +PR: [#30](https://github.com/agentculture/org/pull/30) + +## Intent + +Give matching agent-profile information cards one hierarchy and responsive grid +without turning every rectangular surface into the same component. + +## Actual Delivery + +| Plan task | Status | What landed | +|---|---|---| +| `t1` shared component | delivered | `StructuredCard.astro` owns optional metadata/footer, serif title, 16px body, featured span, reveal delay, and the responsive grid. | +| `t2` Devague | delivered | Method moves and operator skills use 2 authored calls for 14 cards; command titles retain code semantics. | +| `t3` Colleague | delivered | Five families use 5 authored calls for 25 cards; metadata and compact command footers retain their meaning. | +| `t4` Reachy and Lobes | delivered | Four Reachy families and one Lobes family use 5 authored calls for 31 cards. | +| `t5` validation | delivered | The production build and focused semantic/responsive review covered ordering, command treatment, absent copy controls, and explicit exclusions. | + +## Final Decisions + +- Shared treatment is based on the metadata/title/body/footer information model, + not visual similarity alone. +- Command titles remain selectable semantic code and do not become buttons. +- The Devague pipeline initially matched the card family, then moved to a ruled + reference list so the animated flow remained the section's visual + protagonist. Its seven rows are therefore excluded from the delivery + snapshot. +- Directory/library links, article evidence, terminals, tables, measured + statistics, gate previews, closing bands, and presentation cards stay local. + +## Evidence + +- delivery snapshot: 12 authored component calls render 70 cards across four + agent profiles +- route counts are Devague 14, Colleague 25, Reachy Mini CLI 25, and Lobes 6 +- built cards preserve metadata → title → body → footer order +- shared grids contain three-column desktop, two-column intermediate, and + one-column narrow rules +- excluded routes render no structured-card markers +- the Astro production build passes + +## Boundaries + +- no card adds clipboard behavior or a copy control +- future card families must match the semantic contract before adopting the + component diff --git a/docs/plans/2026-07-21-site-ux-review.md b/docs/plans/2026-07-21-site-ux-review.md new file mode 100644 index 0000000..15bf6c2 --- /dev/null +++ b/docs/plans/2026-07-21-site-ux-review.md @@ -0,0 +1,75 @@ +# Build Plan — site-ux-review + +slug: `site-ux-review` · status: `delivered in draft PR #30` + +> Convert the accepted UX-review findings into named shared patterns, migrate +> the current site, and leave a concise record of final decisions. + +## Tasks + +### t1 — Establish the shared system and containment rules + +- add named typography, leading, tracking, rail, measure, diagram-spacing, and + sticky-header roles to the global stylesheet +- assign every authored container an explicit rail without changing the + presentation deck's independent content width +- review token use, rail ownership, terminal legibility, diagram spacing, gate + previews, and the sticky header across representative pages +- acceptance: the production build succeeds for twelve routes and manual review + confirms the shared roles without flattening page-specific layouts + +### t2 — Unify navigation, wayfinding, and destinations + +- centralize header and footer navigation data, including grouped Agents and + Library menus and the external Learn product +- make agent-directory groups stable destinations and use whole-card links with + explicit destination labels +- apply the shared destination-card and external-link behaviors to matching + surfaces +- acceptance: focused navigation tests cover route ownership, grouped + destinations, footer derivation, and safe new-tab behavior; all links pass the + built-site link check + +### t3 — Extract proven agent-page patterns + +- add shared section-introduction, structured-card, closing-band, and inline-code + components +- migrate only the page families that match each semantic pattern +- align terminal legibility and diagram spacing while retaining the four + agent-specific terminal and diagram implementations +- acceptance: source review confirms repeated markup moved into shared + components while other card families and the presentation deck remain local + +### t4 — Complete the Devague story and pipeline + +- model three guided capture sessions and resolve every excerpt from the + immutable capture source +- add session, story-beat, transcript-modal, and read-only human-gate preview + treatments +- repair the flow sequence and replace the competing stage-card grid with a + ruled seven-row reference list +- acceptance: the Astro build resolves every story anchor, transcripts remain + complete and keyboard accessible, and the pipeline reference remains separate + from structured cards + +### t5 — Reconcile the final branch + +- remove experiments that did not survive review, including breadcrumbs and + local contents navigation +- record adopted, superseded, and deferred directions without retaining + generated review artifacts +- run Python, Markdown, Astro, focused navigation, presentation, link, and + repository-doctor validation +- acceptance: the final PR diff contains source, tests, and formal + spec/plan/delivery records only; no generated review bundle remains + +## Risks + +- navigation and footer data can drift if a surface stops deriving from the + typed model; focused tests pin the durable ownership rules +- component extraction can erase page meaning if it is based on appearance + alone; every shared component keeps explicit exclusions +- Astro scoped styles can disappear from built output; inspect representative + built pages where styling is behaviorally significant +- dated review measurements can be mistaken for current state; the delivery + record is the final reconciliation point diff --git a/docs/plans/2026-07-23-global-section-opener.md b/docs/plans/2026-07-23-global-section-opener.md new file mode 100644 index 0000000..5297b82 --- /dev/null +++ b/docs/plans/2026-07-23-global-section-opener.md @@ -0,0 +1,48 @@ +# Build Plan — global-section-opener + +slug: `global-section-opener` · status: `delivered in draft PR #30` + +> Extract the repeated long-form opening grammar without changing page-owned +> content or composition. + +## Tasks + +### t1 — Add the shared component + +- create `SectionIntro.astro` with eyebrow, stable `h2`, optional post-title + content, introduction paragraphs, title-spacing choice, and reveal choice +- use the shared heading and prose measures +- acceptance: source and built output contain the component's semantic markers, + measures, and reduced-motion-safe reveal behavior + +### t2 — Migrate the agent profiles + +- replace repeated opening markup in Devague, Colleague, Lobes, and Reachy Mini + CLI +- label each migrated parent section with its component heading +- acceptance: existing copy, section IDs, reveal timing, accessible labels, and + downstream content remain + +### t3 — Migrate the article beats + +- use one component call inside the existing eight-beat loop +- preserve optional definitions, the first-paragraph lede, paragraph-level + reveals, evidence notes, and beat layout +- acceptance: all eight rendered headings keep their stable IDs and definitions + remain between title and prose + +### t4 — Document and validate the migration + +- record the adopted surfaces, semantic requirements, article ordering, and + presentation exclusion +- build the site and review representative agent and article output +- acceptance: the production build passes; semantic order, readable measures, + reduced-motion behavior, and the presentation exclusion survive review + +## Risks + +- boolean false attributes can render as literal HTML attributes; use explicit + template branches for optional reveal markers +- Astro scoped styles can miss component-generated markup; inspect built output, + not source alone +- article definitions can move during extraction; verify their rendered order diff --git a/docs/plans/2026-07-23-global-structured-card.md b/docs/plans/2026-07-23-global-structured-card.md new file mode 100644 index 0000000..27b2c3f --- /dev/null +++ b/docs/plans/2026-07-23-global-structured-card.md @@ -0,0 +1,50 @@ +# Build Plan — global-structured-card + +slug: `global-structured-card` · status: `delivered in draft PR #30` + +> Migrate metadata-led agent-profile information cards to one semantic +> component while preserving different card families. + +## Tasks + +### t1 — Add the shared card and grid + +- create `StructuredCard.astro` with optional metadata/footer, code-title + semantics, featured span, reveal timing, and namespaced grid styles +- acceptance: metadata → title → body → footer order, 16px body copy, 52rem + three-to-two-to-one grid, and no client-side copy behavior + +### t2 — Migrate Devague + +- migrate method moves and operator skills +- keep the lead method card featured and command titles semantic +- acceptance: method and operator-skill cards preserve their content and + semantics; the pipeline remains a separate ruled reference list + +### t3 — Migrate Colleague + +- migrate paradigm, tiers, work loop, minds, and surfaces +- keep tier/mind context as metadata and command strings as compact footers +- acceptance: every migrated field retains its meaning and reading order + +### t4 — Migrate Reachy Mini CLI and Lobes + +- migrate four Reachy families and the Lobes role family +- preserve source copy, repository/model strings, and page order +- acceptance: source copy, repository/model strings, and page order remain + +### t5 — Document and validate inclusion and exclusion + +- record the adopted families, semantic order, responsive behavior, command + treatment, absent copy controls, and intentional exclusions +- build the site and review representative card families at narrow and wide + viewports +- acceptance: the production build passes and excluded families remain local + +## Risks + +- long command titles can overflow narrow columns; allow semantic code to wrap +- equal-height desktop rows can create dead space on mobile; use natural rows at + the one-column layout +- later pipeline changes can invalidate recorded counts; treat counts as a + delivery snapshot and review current source for present inventory diff --git a/docs/specs/2026-07-21-site-ux-review.md b/docs/specs/2026-07-21-site-ux-review.md new file mode 100644 index 0000000..8c80725 --- /dev/null +++ b/docs/specs/2026-07-21-site-ux-review.md @@ -0,0 +1,108 @@ +# site-ux-review + +> Turn the measured July 2026 UX review into shared site patterns +> without flattening the page-specific compositions that give AgentCulture its +> character. + +## Audience + +- visitors moving between the site shell, agent directory, agent profiles, + articles, presentations, and external ecosystem destinations +- maintainers adding routes, cards, navigation entries, terminal evidence, or + long-form sections +- agents that need one reviewable statement of the accepted UX requirements + rather than a collection of prototypes and evolving handoff notes + +## Baseline findings + +The review measured the static site at commit `d71a719`, when the build emitted +eight routes. These findings describe that dated baseline, not the current +branch: + +| # | Finding | Accepted requirement | +|---|---|---| +| 1 | Agent cards used one visual treatment for internal pages, repositories, and another hosted product. | Expose the destination kind before activation. | +| 2 | Only the agent name was clickable inside a card-sized visual target. | Make the complete destination card interactive. | +| 3 | Directory introduction copy said every entry linked to a repository. | Keep self-description aligned with the mixed destination model. | +| 4 | Six agent groups had no stable wayfinding. | Give every group a stable fragment and expose grouped navigation. | +| 5 | Learn looked internal even though this repository did not build `/learn/`. | Model Learn as an external product destination. | +| 6 | Four agent pages repeated shared presentation decisions independently. | Extract semantic patterns where the pages genuinely agree; keep bespoke compositions local. | +| 7 | External destinations had no consistent visual or assistive cue. | Apply one safe external-link behavior. | + +## Requirements + +### Navigation and destinations + +- The header uses one typed navigation model with direct links for Framework + and Engage, grouped menus for Agents and Library, and an external Learn call + to action. +- The Library menu exposes browse-all destinations plus a deliberately capped + featured selection; it does not grow automatically with every library item. +- The footer is a grouped sitemap derived from the same navigation data and + exposes correct current states. +- Agent directory groups keep stable IDs. Agent cards state whether they lead + to an agent page, a site, or a repository. +- Internal and external destination cards share one interaction model. + External destinations open in a new tab with `noopener noreferrer`, a visible + external icon, and assistive text. + +### Shared design foundations + +- Global type, leading, tracking, rail, measure, diagram-spacing, and sticky + header-offset roles live in `site-astro/src/styles/global.css`. +- Every authored `.container` receives an explicit page, shell, wide, or deck + rail role. Readable heading and prose measures remain nested inside those + outer rails. +- Shared components own repeated semantic patterns: primary navigation, + destination cards, agent-directory cards, section introductions, structured + information cards, closing bands, inline code, and external-link cues. +- Agent-specific diagrams, page order, terminal content, article beats, and + presentation slide layouts remain page-owned. +- Terminal components retain their different content shapes while sharing + legible type, spacing, overflow, and fixed dark-surface rules. + +### Devague experience + +- The real-captures section presents three named working sessions and fourteen + narrated excerpts so a non-technical reader can follow the evidence. +- Excerpts resolve from immutable capture data by exact anchors. Complete + transcripts remain accessible from a keyboard-operable modal. +- Human-gate examples are read-only previews; they do not add copy controls. +- The pipeline keeps its animated flow as the visual protagonist and presents + the seven stages as a quieter ruled reference list. +- The method and operator-skills sections use shared structured cards only + where their metadata, title, body, and footer semantics match. + +## Preserve + +- WCAG AA contrast in both themes +- one logical heading hierarchy per route +- keyboard-accessible scroll regions and dialogs +- complete no-JavaScript and reduced-motion renderings +- no page-level horizontal overflow at narrow widths +- static output with no client-side network dependency +- verbatim transcript and provenance requirements +- bespoke diagrams and presentation compositions + +## Boundaries + +- Do not add breadcrumbs or local contents navigation in this change. +- Do not create a generic `AgentPage` or `Terminal` abstraction until a later + task proves a stable shared interface. +- Do not change Learn source, deployment, or ownership. +- Do not make future pages adopt components automatically. +- Do not replace semantically distinct card families merely because they share + a rectangular surface. +- Do not retain generated review pages or static mock bundles as a second + source of truth. + +## Success signals + +- All twelve routes build with the typed navigation and explicit rail roles. +- Shared components own repeated markup while intentional exclusions remain + page-local and reviewable. +- Devague story anchors resolve from the capture source during the build, and + all full transcripts remain reachable. +- The implementation, focused tests, and + [delivery record](../deliveries/2026-07-21-site-ux-review.md) agree about + semantics, exclusions, and deferred work. diff --git a/docs/specs/2026-07-23-global-section-opener.md b/docs/specs/2026-07-23-global-section-opener.md new file mode 100644 index 0000000..232ebf4 --- /dev/null +++ b/docs/specs/2026-07-23-global-section-opener.md @@ -0,0 +1,53 @@ +# global-section-opener + +> Long-form sections share one semantic opening: an eyebrow, a stable section +> heading, optional material between the title and prose, and a readable +> introduction. + +## Audience + +- readers scanning the four long agent profiles and the long-form article +- maintainers adding or changing a long-form section +- agents deciding whether a page should use the shared opener or keep a local + presentation pattern + +## Contract + +- `SectionIntro.astro` owns the eyebrow, `h2`, heading ID, optional + `after-title` slot, prose wrapper, title spacing, and reveal behavior. +- The parent section uses `aria-labelledby` pointing at the component's heading. +- Headings use `--ac-measure-heading`; introductory prose uses + `--ac-measure-prose`. +- Agent pages can reveal the introductory group as one unit. +- The article can place definitions between its heading and prose, keep the + first paragraph as a lede, and reveal paragraphs individually. +- The shared component uses built-output-safe styling and leaves absent reveal + attributes genuinely absent. + +## Adopted Surfaces + +- six Devague sections +- nine Colleague sections +- five Lobes sections +- seven Reachy Mini CLI sections +- one article loop rendering eight beat openings + +At delivery, this was 28 authored component calls and 35 rendered openings. + +## Boundaries + +- Fast-facts sections keep their existing local structure. +- The seven-slide presentation keeps its slide-owned eyebrow pattern. +- Section order, IDs, copy, definitions, evidence notes, and downstream page + compositions remain page-owned. +- The component is selected deliberately; it is not automatic scaffolding for + every future section. + +## Success Signals + +- migrated pages contain no copied eyebrow/heading/prose opener markup +- all parent regions and component headings retain matching accessible IDs +- article definitions remain between the heading and prose +- no `data-reveal="false"` attributes appear in built output +- the Astro build succeeds and representative agent/article pages pass semantic, + visual, keyboard, and reduced-motion review diff --git a/docs/specs/2026-07-23-global-structured-card.md b/docs/specs/2026-07-23-global-structured-card.md new file mode 100644 index 0000000..cc8e081 --- /dev/null +++ b/docs/specs/2026-07-23-global-structured-card.md @@ -0,0 +1,50 @@ +# global-structured-card + +> Agent-profile information with the same metadata → title → body → footer +> meaning shares one card and grid contract; visually similar but semantically +> different surfaces remain independent. + +## Audience + +- readers comparing structured information across the four agent profiles +- maintainers adding metadata-led informational card families +- agents deciding whether a proposed card matches the shared semantic contract + +## Contract + +- `StructuredCard.astro` owns optional metadata, a serif `h3`, 16px body copy, + an optional compact footer, featured span, and reveal delay. +- Code-like titles keep semantic `` markup without becoming controls. +- The shared grid is capped at 52rem and reflows from three to two to one + columns. +- Metadata precedes the title, the body follows it, and an optional footer + closes the card. +- Cards contain no clipboard behavior or copy control. + +## Adopted Surfaces + +- Devague method moves and operator skills: 2 calls, 14 cards +- Colleague paradigm, tiers, work loop, minds, and surfaces: 5 calls, 25 cards +- Reachy Mini CLI capabilities, owner model, senses, and agent-first surfaces: + 4 calls, 25 cards +- Lobes roles: 1 call, 6 cards + +At delivery, this was 12 authored calls and 70 rendered cards. + +## Boundaries + +- The Devague pipeline is a ruled seven-row reference list, not a structured-card + family. +- Directory and library destinations use `DestinationCard`. +- Article evidence, terminals, tables, measured statistics, human-gate rows, + closing bands, and presentation cards remain semantically distinct. +- Equal visual treatment is not sufficient reason to adopt this component. + +## Success Signals + +- built cards retain metadata → title → body → footer order +- all card grids reflow without page overflow +- only Devague's command titles use code semantics +- excluded routes render no structured-card markers +- the Astro build succeeds and representative card families pass semantic, + visual, keyboard, and responsive review diff --git a/pyproject.toml b/pyproject.toml index 54f3a19..50021fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "org" -version = "0.18.2" +version = "0.19.0" description = "The AgentCulture org site — source of the web presence published to AgentCulture.org. Replaces the deleted landing-page repo. Not distributed on PyPI: the CLI stays repo-local; the deliverable is the published site." readme = "README.md" license = "Apache-2.0" diff --git a/site-astro/scripts/check-presentations.mjs b/site-astro/scripts/check-presentations.mjs index e58a408..66b3949 100644 --- a/site-astro/scripts/check-presentations.mjs +++ b/site-astro/scripts/check-presentations.mjs @@ -288,8 +288,8 @@ check("site-wide Articles + Presentations wayfinding", () => { const footer = requireRegion(html, "footer", "site-footer", path); for (const route of [articlesRoute, presentationsRoute]) { assert( - linksTo(header.outer, route).length === 1, - `${path} header must contain exactly one ${route} link`, + linksTo(header.outer, route).length === 2, + `${path} header must contain desktop and mobile ${route} links`, ); assert( linksTo(footer.outer, route).length === 1, @@ -828,53 +828,83 @@ check("current nav state per surface", () => { { label: "articles index", html: articlesIndexHtml, - activeLabel: "Articles", - activeHref: articlesRoute, + exactHref: articlesRoute, + footerLabel: "Articles", + footerHref: articlesRoute, }, { label: "article", html: articleHtml, - activeLabel: "Articles", - activeHref: articlesRoute, + exactHref: articleRoute, + footerLabel: undefined, + footerHref: undefined, }, { label: "presentations index", html: presentationsIndexHtml, - activeLabel: "Presentations", - activeHref: presentationsRoute, + exactHref: presentationsRoute, + footerLabel: "Presentations", + footerHref: presentationsRoute, }, { label: "deck", html: deckHtml, - activeLabel: "Presentations", - activeHref: presentationsRoute, + exactHref: deckRoute, + footerLabel: undefined, + footerHref: undefined, }, ]; - for (const { label, html, activeLabel, activeHref } of surfaces) { + for (const { + label, + html, + exactHref, + footerLabel, + footerHref, + } of surfaces) { const header = requireRegion(html, "header", "site-header", label); const footer = requireRegion(html, "footer", "site-footer", label); - for (const [regionLabel, region] of [ - ["Header", header], - ["Footer", footer], - ]) { - const current = anchors(region.outer).filter( - (anchor) => anchor.attrs["aria-current"] === "page", - ); - assert( - current.length === 1, - `${label} ${regionLabel} needs exactly one current link, found ${current.length}`, - ); - assert( - current[0].attrs.href === activeHref && current[0].text === activeLabel, - `${label} ${regionLabel} current link must be ${activeLabel}`, - ); - } + + const currentHeaderOwners = openings(header.outer, "li").filter( + (item) => item["data-nav-current"] === "true", + ); + assert( + currentHeaderOwners.length === 2 && + currentHeaderOwners.every( + (item) => item["data-nav-item"] === "Library", + ), + `${label} must be owned by Library in both responsive Header navs`, + ); + + const currentHeaderLinks = anchors(header.outer).filter( + (anchor) => anchor.attrs["aria-current"] === "page", + ); + assert( + currentHeaderLinks.length === 2 && + currentHeaderLinks.every( + (anchor) => anchor.attrs.href === exactHref, + ), + `${label} Header must mark ${exactHref} as the exact current destination`, + ); + + const currentFooterLinks = anchors(footer.outer).filter( + (anchor) => anchor.attrs["aria-current"] === "page", + ); + assert( + currentFooterLinks.length === (footerHref ? 1 : 0) && + (!footerHref || + (currentFooterLinks[0].attrs.href === footerHref && + currentFooterLinks[0].text === footerLabel)), + footerHref + ? `${label} Footer current link must be ${footerLabel}` + : `${label} Footer must not fall back to its Library index`, + ); + const pageCurrent = anchors(html).filter( (anchor) => anchor.attrs["aria-current"] === "page", ); assert( - pageCurrent.length === 2, - `${label} must have current state in Header and Footer only; found ${pageCurrent.length}`, + pageCurrent.length === (footerHref ? 3 : 2), + `${label} must have exact current state only where its destination is rendered; found ${pageCurrent.length}`, ); } }); diff --git a/site-astro/src/components/AgentDirectoryCard.astro b/site-astro/src/components/AgentDirectoryCard.astro new file mode 100644 index 0000000..05e185d --- /dev/null +++ b/site-astro/src/components/AgentDirectoryCard.astro @@ -0,0 +1,57 @@ +--- +import type { AgentEntry } from "../data/types"; +import DestinationCard from "./DestinationCard.astro"; + +interface Props { + agent: AgentEntry; +} + +const { agent } = Astro.props; +const destinationLabels = { + "agent-page": "Agent page", + site: "Visit site", + repository: "Repository", +} as const; +const destination = destinationLabels[agent.destinationKind]; +--- + +{ + agent.url ? ( + + ) : ( +
+

{agent.name}

+

{agent.role}

+
+ ) +} + + diff --git a/site-astro/src/components/CaptureSession.astro b/site-astro/src/components/CaptureSession.astro new file mode 100644 index 0000000..99dd1ed --- /dev/null +++ b/site-astro/src/components/CaptureSession.astro @@ -0,0 +1,64 @@ +--- +import CaptureSessionHeader from "./CaptureSessionHeader.astro"; +import CaptureStoryBeat from "./CaptureStoryBeat.astro"; +import DevagueTerminal from "./DevagueTerminal.astro"; +import { + getCapturePane, + type SessionStory, +} from "../data/devague-story"; + +interface Props { + session: SessionStory; +} + +const { session } = Astro.props; +const titleId = `capture-session-${session.n}-title`; +const beatsId = `capture-session-${session.n}-beats`; +const heroPane = getCapturePane(session.heroPaneId); +const sessionPanes = session.paneIds.map((paneId) => getCapturePane(paneId)); +--- + +
+
+ + +
+
    + {session.beats.map((beat) => )} +
+
+ +
+
+ +
+
diff --git a/site-astro/src/components/CaptureSessionHeader.astro b/site-astro/src/components/CaptureSessionHeader.astro new file mode 100644 index 0000000..4281de0 --- /dev/null +++ b/site-astro/src/components/CaptureSessionHeader.astro @@ -0,0 +1,20 @@ +--- +import type { SessionStory } from "../data/devague-story"; + +interface Props { + session: SessionStory; + titleId: string; +} + +const { session, titleId } = Astro.props; +--- + +
+

+ Session {session.n}{" · "}{session.date}{" · "}{session.version} +

+

{session.title}

+
+ {session.intro.map((paragraph) =>

{paragraph}

)} +
+
diff --git a/site-astro/src/components/CaptureStoryBeat.astro b/site-astro/src/components/CaptureStoryBeat.astro new file mode 100644 index 0000000..7438f8d --- /dev/null +++ b/site-astro/src/components/CaptureStoryBeat.astro @@ -0,0 +1,69 @@ +--- +import InlineCodeText from "./InlineCodeText.astro"; +import { + resolveStoryBeat, + type StoryBeat, +} from "../data/devague-story"; + +interface Props { + beat: StoryBeat; +} + +const { beat } = Astro.props; +const { pane, lines } = resolveStoryBeat(beat); +const leg = pane.id.split("-")[0]; +const promptColour: Record = { + frame: "#7fdcc9", + plan: "#f2b774", + scope: "#7fb3f2", + challenge: "#e6cd7a", + deviate: "#f2789a", + summary: "#b49cf2", +}; +--- + +
  • + +
    +

    {beat.headline}

    +

    {beat.narration}

    +
    + { + lines.map((line) => ( +

    + {line.kind === "cmd" && ( + + )} + {line.kind === "ellipsis" && ( + + )} + +

    + )) + } + {beat.note && ( +

    + +

    + )} +
    +
    +
  • diff --git a/site-astro/src/components/CaptureTranscriptModal.astro b/site-astro/src/components/CaptureTranscriptModal.astro new file mode 100644 index 0000000..06c2cfe --- /dev/null +++ b/site-astro/src/components/CaptureTranscriptModal.astro @@ -0,0 +1,456 @@ +--- +import DevagueTerminal from "./DevagueTerminal.astro"; +import { + getCapturePane, + sessions, +} from "../data/devague-story"; + +const paneOrder = sessions.flatMap(({ paneIds }) => paneIds); +--- + + + + + + + + diff --git a/site-astro/src/components/ClosingBand.astro b/site-astro/src/components/ClosingBand.astro new file mode 100644 index 0000000..07e1162 --- /dev/null +++ b/site-astro/src/components/ClosingBand.astro @@ -0,0 +1,112 @@ +--- +// The agent-page closing treatment approved in the Devague mock: agent name, +// thread flourish, existing closing copy, then the existing actions. This +// stays inside
    ; Footer.astro remains the page's only real footer. +interface ClosingAction { + href: string; + label: string; + treatment?: "link" | "code"; +} + +interface Props { + name: string; + paragraphs: readonly string[]; + actions: readonly ClosingAction[]; +} + +const { name, paragraphs, actions } = Astro.props; +--- + +
    +
    +
    + {name} + +
    + +
    + {paragraphs.map((paragraph) =>

    {paragraph}

    )} +

    + { + actions.map((action) => { + const opensInNewTab = /^https?:\/\//.test(action.href); + return ( + + {action.treatment === "code" ? ( + {action.label} + ) : ( + <>{action.label} → + )} + + ); + }) + } +

    +
    +
    +
    + + diff --git a/site-astro/src/components/ColleagueTerminal.astro b/site-astro/src/components/ColleagueTerminal.astro index c0824d2..f84378a 100644 --- a/site-astro/src/components/ColleagueTerminal.astro +++ b/site-astro/src/components/ColleagueTerminal.astro @@ -225,8 +225,9 @@ const rendered = pane.lines padding: 0.7rem 1.15rem; border-bottom: 1px solid rgba(233, 236, 248, 0.1); font-family: var(--font-mono); - font-size: 0.72rem; - letter-spacing: 0.03em; + font-size: var(--ac-type-meta); + line-height: var(--ac-leading-ui); + letter-spacing: var(--ac-tracking-flat); color: #a9b0cf; flex-wrap: wrap; row-gap: 0.35rem; @@ -279,9 +280,10 @@ const rendered = pane.lines border-radius: 999px; border: 1px solid currentColor; font-weight: 650; - letter-spacing: 0.06em; + line-height: var(--ac-leading-ui); + letter-spacing: var(--ac-tracking-caps); text-transform: uppercase; - font-size: 0.62rem; + font-size: var(--ac-type-micro); } .accent-identity .accent-tag { @@ -347,8 +349,8 @@ const rendered = pane.lines .muted-source { color: #8790b8; - font-size: 0.9em; - letter-spacing: 0.01em; + font-size: var(--ac-type-micro); + letter-spacing: var(--ac-tracking-flat); } pre { @@ -356,11 +358,18 @@ const rendered = pane.lines padding: 1.05rem 1.15rem 1.2rem; overflow-x: auto; font-family: var(--font-mono); - font-size: 0.78rem; - line-height: 1.7; + font-size: var(--ac-type-terminal); + line-height: var(--ac-leading-card); + letter-spacing: var(--ac-tracking-flat); color: #c7cde8; } + pre > code { + font-size: inherit; + line-height: inherit; + letter-spacing: inherit; + } + /* NOTE on :global() below: the transcript (.tl / .tl-cmd / .tl-out / .tl-ellipsis / .ch / .prompt / .cut-mark / .cut-text) arrives as a plain HTML string via set:html, not as markup this file's own @@ -407,7 +416,8 @@ const rendered = pane.lines align-items: baseline; color: #8790b8; font-style: italic; - font-size: 0.85em; + font-size: var(--ac-type-meta); + line-height: var(--ac-leading-card); } .term :global(.cut-mark) { diff --git a/site-astro/src/components/DestinationCard.astro b/site-astro/src/components/DestinationCard.astro new file mode 100644 index 0000000..a08c649 --- /dev/null +++ b/site-astro/src/components/DestinationCard.astro @@ -0,0 +1,100 @@ +--- +import ExternalLinkIcon from "./ExternalLinkIcon.astro"; + +interface Props { + href: string; + title: string; + description: string; + destinationLabel: string; + titleStyle?: "display" | "mono"; + className?: string; +} + +const { + href, + title, + description, + destinationLabel, + titleStyle = "display", + className, +} = Astro.props; +const opensInNewTab = /^https?:\/\//.test(href); +--- + + +

    {title}

    +

    {description}

    + + {destinationLabel} + { + opensInNewTab ? ( + <> + + (opens in a new tab) + + ) : ( + + ) + } + +
    + + diff --git a/site-astro/src/components/DevagueFlow.astro b/site-astro/src/components/DevagueFlow.astro index c5dc83a..c9a78cd 100644 --- a/site-astro/src/components/DevagueFlow.astro +++ b/site-astro/src/components/DevagueFlow.astro @@ -29,13 +29,14 @@ // A spec opens the build; a summary closes it. // // Motion is compositor-only (transform + opacity, nothing else), on the -// site's calm easings. It plays ONCE the first time it scrolls into view -// (the LobesTerminal pattern: an IntersectionObserver toggles `.is-playing`; -// the class is the only thing JS touches — no network, no layout writes), -// then holds the assembled frame. Under prefers-reduced-motion, or with no -// JS, nothing is hidden and nothing moves: the authored DOM already IS the -// finished pipeline — every stage present, every claim confirmed, the gate -// open — so the method stays fully legible as a still. +// site's calm easings. It plays ONCE the first time each part scrolls into +// view (the LobesTerminal pattern: an IntersectionObserver toggles +// `.is-playing` on each stage and connector; the class is the only thing JS +// touches — no network, no layout writes), then holds the assembled frame. +// Under prefers-reduced-motion, or with no JS, nothing is hidden and nothing +// moves: the authored DOM already IS the finished pipeline — every stage +// present, every claim confirmed, the gate open — so the method stays fully +// legible as a still. // // Labels default to real devague vocabulary (verified against `devague // learn` on 0.19.0). The page may override any stage label via `labels`. @@ -96,7 +97,7 @@ const CLAIMS = ["audience", "after_state", "boundary"]; >
      -
    1. +
    2. -
    3. +
    4. -
    5. +
    6. - + -
    7. +
    8. - + -
    9. +
    10. - + -
    11. +
    12. - + -
    13. +
    14. - + -
    15. +
    16. - + -
    17. +
    18. {L.summary} @@ -775,14 +776,103 @@ const CLAIMS = ["audience", "after_state", "boundary"]; } } + /* When the diagram stacks, each item gets its own short local clock. + This preserves the same stage order as the desktop sequence instead of + letting later stages finish off-screen before the user reaches them. */ + @media (max-width: 66rem) and (prefers-reduced-motion: no-preference) { + .link-line, + .frame-claims, + .gate-glyph, + .spec-doc, + .challenge-glyph, + .wave-root, + .build-glyph, + .ledger-glyph, + .summary-doc { + --d: 0.15s !important; + } + + .claim:nth-child(1) { + --d: 1.25s !important; + } + + .claim:nth-child(2) { + --d: 1.85s !important; + } + + .claim:nth-child(3) { + --d: 2.45s !important; + } + + :global(html.js) .flow .gate-block { + transition-delay: 1.75s !important; + } + + :global(html.js) .flow .gate-check { + transition-delay: 2.25s !important; + } + + :global(html.js) .stage.is-playing .gate-leaf-l, + :global(html.js) .stage.is-playing .gate-leaf-r { + animation-delay: 0.65s !important; + } + + .challenge-finding { + --d: 0.85s !important; + } + + .finding-open, + .finding-solid { + --d: 1.45s !important; + } + + .challenge-lens { + --d: 0.35s !important; + } + + .wave-lane:nth-child(2) { + --d: 0.45s !important; + } + + .wave-lane:nth-child(3) { + --d: 0.75s !important; + } + + .wave-lane:nth-child(4) { + --d: 1.05s !important; + } + + .ledger-entry { + --d: 0.75s !important; + } + + .summary-tick:nth-child(4) { + --d: 0.7s !important; + } + + .summary-tick:nth-child(6) { + --d: 0.95s !important; + } + + .summary-tick:nth-child(8) { + --d: 1.2s !important; + } + + .stage-label, + .stage-kind { + --d: 0.5s !important; + } + } + /* ---------- motion ---------- Every animated property below is transform or opacity only. Hidden / pre-play states apply ONLY under html.js + no-preference (mirroring the site's reveal system and LobesTerminal); the base rules above already render the finished, composed pipeline. The `.is-playing` class — set - once by the observer when the figure scrolls into view — drives each - element from its pre-play pose to the composed pose, staggered by a - per-element `--d` delay, then holds. No loop, no reset flicker. */ + once by the observer when each stage or connector scrolls into view — + drives its elements from their pre-play poses to the composed poses, + staggered by the per-element `--d` delay, then holds. No loop, no reset + flicker. */ @media (prefers-reduced-motion: no-preference) { /* idle breathing on the seed and finished nodes — calm, infinite */ .idea-seed { @@ -830,6 +920,24 @@ const CLAIMS = ["audience", "after_state", "boundary"]; transition-delay: var(--d, 0s); } + :global(html.js) .flow .gate-glyph { + opacity: 0; + transform: translateY(0.6rem) scale(0.9); + transition: + opacity 0.7s var(--ease-out), + transform 0.7s var(--ease-out); + transition-delay: var(--d, 0s); + } + + :global(html.js) .flow .wave-root { + opacity: 0; + transform: scale(0.5); + transition: + opacity 0.5s var(--ease-out), + transform 0.5s var(--ease-gentle); + transition-delay: var(--d, 0s); + } + /* challenge: the lens starts up at the examined rules and sweeps down the page to rest over the finding — one calm, transform-only move */ :global(html.js) .flow .challenge-lens { @@ -917,7 +1025,7 @@ const CLAIMS = ["audience", "after_state", "boundary"]; :global(html.js) .flow .gate-block { opacity: 1; transition: opacity 0.4s var(--ease-out); - transition-delay: 3.7s; + transition-delay: 5.7s; } :global(html.js) .flow .gate-check { @@ -928,87 +1036,105 @@ const CLAIMS = ["audience", "after_state", "boundary"]; transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-gentle); - transition-delay: 4.2s; + transition-delay: 6.2s; } /* --- played poses (composed) --- */ - :global(html.js) .flow.is-playing .link-line { + :global(html.js) .link.is-playing .link-line { transform: none; } - :global(html.js) .flow.is-playing .frame-claims { + :global(html.js) .stage.is-playing .frame-claims { opacity: 1; transform: none; } - :global(html.js) .flow.is-playing .claim-open { + :global(html.js) .stage.is-playing .claim-open { opacity: 0; } - :global(html.js) .flow.is-playing .claim-solid { + :global(html.js) .stage.is-playing .claim-solid { opacity: 1; transform: scale(1); } - :global(html.js) .flow.is-playing .spec-doc, - :global(html.js) .flow.is-playing .build-glyph { + :global(html.js) .stage.is-playing .spec-doc, + :global(html.js) .stage.is-playing .build-glyph, + :global(html.js) .stage.is-playing .gate-glyph { opacity: 1; transform: none; } - :global(html.js) .flow.is-playing .wave-lane { + :global(html.js) .stage.is-playing .wave-lane { opacity: 1; transform: scaleX(1); } - :global(html.js) .flow.is-playing .gate-block { + :global(html.js) .stage.is-playing .wave-root { + opacity: 1; + transform: scale(1); + } + + :global(html.js) .stage.is-playing .gate-block { opacity: 0; } - :global(html.js) .flow.is-playing .gate-check { + :global(html.js) .stage.is-playing .gate-check { opacity: 1; transform: scale(1); } - :global(html.js) .flow.is-playing .challenge-glyph, - :global(html.js) .flow.is-playing .ledger-glyph, - :global(html.js) .flow.is-playing .summary-doc { + :global(html.js) .stage.is-playing .challenge-glyph, + :global(html.js) .stage.is-playing .ledger-glyph, + :global(html.js) .stage.is-playing .summary-doc { opacity: 1; transform: none; } - :global(html.js) .flow.is-playing .challenge-lens { + :global(html.js) .stage.is-playing .challenge-lens { transform: none; } - :global(html.js) .flow.is-playing .challenge-finding { + :global(html.js) .stage.is-playing .challenge-finding { opacity: 1; } - :global(html.js) .flow.is-playing .finding-open, - :global(html.js) .flow.is-playing .entry-open { + :global(html.js) .stage.is-playing .finding-open, + :global(html.js) .stage.is-playing .entry-open { opacity: 0; } - :global(html.js) .flow.is-playing .finding-solid, - :global(html.js) .flow.is-playing .entry-solid { + :global(html.js) .stage.is-playing .finding-solid, + :global(html.js) .stage.is-playing .entry-solid { opacity: 1; transform: scale(1); } - :global(html.js) .flow.is-playing .summary-tick { + :global(html.js) .stage.is-playing .summary-tick { opacity: 1; transform: scale(1); } + :global(html.js) .flow .stage-label, + :global(html.js) .flow .stage-kind { + opacity: 0; + transition: opacity 0.5s var(--ease-out); + transition-delay: calc(var(--d, 0s) + 0.35s); + } + + :global(html.js) .stage.is-playing .stage-label, + :global(html.js) .stage.is-playing .stage-kind { + opacity: 1; + } + /* the gate's refuse-then-open beat is inherently multi-step, so it runs as a keyframe (compositor-only). `both` holds the open pose after. */ - :global(html.js) .flow.is-playing .gate-leaf-l { - animation: gate-open-l 3.6s var(--ease-gentle) 1s both; + :global(html.js) .stage.is-playing .gate-leaf-l { + animation: gate-open-l 1.8s var(--ease-gentle) 4.6s both; } - :global(html.js) .flow.is-playing .gate-leaf-r { - animation: gate-open-r 3.6s var(--ease-gentle) 1s both; + :global(html.js) .stage.is-playing .gate-leaf-r { + animation: gate-open-r 1.8s var(--ease-gentle) 4.6s both; } } @@ -1065,10 +1191,10 @@ const CLAIMS = ["audience", "after_state", "boundary"]; diff --git a/site-astro/src/components/DevagueTerminal.astro b/site-astro/src/components/DevagueTerminal.astro index d5401b2..584c85a 100644 --- a/site-astro/src/components/DevagueTerminal.astro +++ b/site-astro/src/components/DevagueTerminal.astro @@ -135,7 +135,7 @@ const rendered = pane.lines {legLabel[leg]} {pane.title} - {pane.context} + {pane.context} devague {pane.devagueVersion} · captured {pane.capturedDate}
       code {
      +    font-size: inherit;
      +    line-height: inherit;
      +    letter-spacing: inherit;
      +  }
      +
         /* NOTE on :global() below: the transcript (.tl / .tl-cmd / .tl-out /
            .tl-ellipsis / .ch / .prompt / .cut-mark / .cut-text) is injected via
            set:html as a plain string — Astro's compiler only stamps its
      @@ -350,7 +359,8 @@ const rendered = pane.lines
           align-items: baseline;
           color: #8790b8;
           font-style: italic;
      -    font-size: 0.85em;
      +    font-size: var(--ac-type-meta);
      +    line-height: var(--ac-leading-card);
         }
       
         .term :global(.cut-mark) {
      diff --git a/site-astro/src/components/ExternalLinkIcon.astro b/site-astro/src/components/ExternalLinkIcon.astro
      new file mode 100644
      index 0000000..77ecaa8
      --- /dev/null
      +++ b/site-astro/src/components/ExternalLinkIcon.astro
      @@ -0,0 +1,20 @@
      +---
      +interface Props {
      +  size?: number;
      +}
      +
      +const { size = 14 } = Astro.props;
      +---
      +
      +
      diff --git a/site-astro/src/components/Footer.astro b/site-astro/src/components/Footer.astro
      index 1924df0..b57841f 100644
      --- a/site-astro/src/components/Footer.astro
      +++ b/site-astro/src/components/Footer.astro
      @@ -1,40 +1,57 @@
       ---
       import site from "../data/site";
       import {
      -  isPrimaryNavCurrent,
      -  primaryNavigation,
      +  footerNavigation,
      +  isFooterNavCurrent,
       } from "../data/navigation";
      +import ExternalLinkIcon from "./ExternalLinkIcon.astro";
       import Mark from "./Mark.astro";
       
       const year = new Date().getFullYear();
       ---
       
       
      -
      -
      - - - {site.hero.title} - - +
      + +

      This site is built and operated by the organization's agents. @@ -46,70 +63,126 @@ const year = new Date().getFullYear(); diff --git a/site-astro/src/components/Header.astro b/site-astro/src/components/Header.astro index 4a495cc..39af3df 100644 --- a/site-astro/src/components/Header.astro +++ b/site-astro/src/components/Header.astro @@ -1,122 +1,484 @@ --- import site from "../data/site"; -import { - isPrimaryNavCurrent, - primaryNavigation, -} from "../data/navigation"; import Mark from "./Mark.astro"; +import PrimaryNavigation from "./PrimaryNavigation.astro"; --- -

    -
    -
    - {devague.method.eyebrow} -

    {devague.method.headline}

    -
    - {devague.method.intro.map((p) =>

    {p}

    )} -
    -
      +
      +
      + +
        { devague.method.moves.map((move, i) => ( -
      1. - -

        {move.verb}

        -

        {move.ask}

        -

        {move.detail}

        -
      2. + )) }
      @@ -127,13 +142,14 @@ import {
      -
      -
      - {devague.reviewLoop.eyebrow} -

      {devague.reviewLoop.headline}

      -
      - {devague.reviewLoop.intro.map((p) =>

      {p}

      )} -
      +
      +
      +
        { devague.reviewLoop.steps.map((step, i) => ( @@ -142,8 +158,32 @@ import { data-reveal style={`--reveal-delay: ${Math.min(i * 0.07, 0.28)}s`} > - {step.cmd} -

        {step.effect}

        +
        +

        + + {" · "} + {step.kind} +

        +

        {step.title}

        +

        + { + step.effect.map((part) => + typeof part === "string" ? part : {part.code} + ) + } +

        +
        + +
        +
        + + human gate +
        + + + {step.cmd} + +
        )) } @@ -152,25 +192,28 @@ import {
      -
      -
      - {devague.skills.eyebrow} -

      {devague.skills.headline}

      -
      - {devague.skills.intro.map((p) =>

      {p}

      )} -
      -
        +
        +
        + +
          { devague.skills.cards.map((card, i) => ( -
        • -

          {card.name}

          - {card.leg} -

          {card.duty}

          -
        • + )) }
        @@ -178,77 +221,29 @@ import {
        -
        -
        - {devague.captures.eyebrow} -

        {devague.captures.headline}

        -
        - {devague.captures.intro.map((p) =>

        {p}

        )} -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        +
        +
        + + {sessions.map((session) => )}

        {devague.captures.provenance}

        +
        -
        -
        - {devague.whatsNext.eyebrow} -

        {devague.whatsNext.headline}

        -
        - {devague.whatsNext.intro.map((p) =>

        {p}

        )} -
        +
        +
        +
        - -
        -
        -
        - {devague.closing.paragraphs.map((p) =>

        {p}

        )} -

        - {devague.closing.repoCta} → - {devague.closing.pypiCta} -

        -
        -
        -
        + + + diff --git a/site-astro/src/pages/agents/lobes.astro b/site-astro/src/pages/agents/lobes.astro index ba797f5..6cca76a 100644 --- a/site-astro/src/pages/agents/lobes.astro +++ b/site-astro/src/pages/agents/lobes.astro @@ -6,6 +6,10 @@ // ../../data/lobes-captures.ts — nothing on this page dials a machine. import Layout from "../../layouts/Layout.astro"; import PageHero from "../../components/PageHero.astro"; +import ClosingBand from "../../components/ClosingBand.astro"; +import DestinationCard from "../../components/DestinationCard.astro"; +import SectionIntro from "../../components/SectionIntro.astro"; +import StructuredCard from "../../components/StructuredCard.astro"; import LobesDiagram from "../../components/LobesDiagram.astro"; import LobesTerminal from "../../components/LobesTerminal.astro"; import site from "../../data/site"; @@ -19,6 +23,7 @@ import { meshThor, meshAsk, } from "../../data/lobes-captures"; + ---
        -
        +
          { lobes.facts.map((fact, i) => ( @@ -40,7 +45,17 @@ import { > {fact.label} - {fact.href ? {fact.value} : fact.value} + {fact.href ? ( + + {fact.value} + + ) : ( + fact.value + )} )) @@ -50,25 +65,23 @@ import {
        -
        -
        - the lobes -

        One machine serves a small fleet of minds

        -
        - {lobes.story.what.map((p) =>

        {p}

        )} -
        -