Skip to content

feat(knowledge): check every specification in the repository as a knowledge record, and convert the native specs - #8288

Open
cixzhang wants to merge 3 commits into
mainfrom
feat/knowledge-records-everywhere
Open

cixzhang wants to merge 3 commits into
mainfrom
feat/knowledge-records-everywhere

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #8500 (the Swift shared rules as architecture records), and carries its commit until it lands. Review the top two commits here: the checker, then the generated schema-5 migration. After it merges, this rebases onto main and reruns the migration.

Maintainer impact

architecture:knowledge-contracts INV27 and DEC-13 say every specification is a knowledge record, but pnpm check:knowledge only reads records in docs/, themes, and the component packages' src/. The seven Swift specs under packages/native/specs/swift/library/ and the package's own TEMPLATE.md skip structure checks, the spec-owner gate, and pnpm specs:for routing, and nothing stops the next package from inventing its own spec format.

Intended invariant

architecture:knowledge-contracts INV27 and DEC-13, and AST-093 FR1:

  • every spec-shaped file (a *.spec.md, or Markdown under a specs/ directory, apart from README.md, plan.md, and the paths discovery ignores) is a valid record at its kind's location, or check:knowledge fails;
  • a Swift component's spec is packages/native/apple/Sources/Astryx/<Name>/<Name>.spec.md, id component:swift/<Name>, and names its core component in platform_of;
  • a package's shared rules are architecture records at packages/<package>/specs/**/<slug>.spec.md, with the id that path gives.

Change

  • Discovery and placement (.github/scripts/knowledge-paths.cjs, scripts/check-knowledge.mjs):
    • Spec-shaped candidates are read from git's tracked and untracked files. Each one must be a valid record at its kind's location.
    • Swift platform component records: the id must follow the path, and platform_of must name component:<Name>. That resolves to a Core or Lab record. Until one exists, packages/core/src/<Name>/ or a <Name>.doc.mjs under packages/core/src/ stands in. The record sits where core keeps that component (AST-093 FR1, with spec(AST-093): a native component lives in the folder where core keeps it (FR1) #8593): its own folder when core uses one, or the folder core keeps it in, as core keeps AvatarStatusDot in Avatar/ and ListItem in List/.
    • A platform record has no anatomy-theming map. A Core or Lab record keeps platform_of: null.
    • Package architecture records: the kind is architecture and the id comes from the path.
  • Schema v5 (docs/schemas/knowledge/v5.json) adds platform_of to component records and lets component ids carry a language (component:swift/Button). The component template moves to v8.
  • Record migration, by script: node scripts/migrate-knowledge-v5.mjs moves every component record to schema 5 with platform_of: null after id, and changes nothing else. It is deterministic and idempotent, and --check lists records that still need it. Its output is the separate final commit. The check:knowledge message for an unmigrated component record names the command.
  • Routing: pnpm specs:for sends a Swift file to its platform record and, through platform_of, to the core record. change-scope treats platform records as spec records and package records like architecture records, so the owner gate covers both.
  • Native specs: converted to architecture records in docs(native): every Swift shared rule is an architecture record #8500, stacked below this PR.
  • INV27's enforcement-gap paragraph is removed, because this change closes all three gaps it lists.

Rebasing

Component records keep landing on main. To rebase: drop the final chore(knowledge): move component records to schema v5 commit, rebase the other two, run node scripts/migrate-knowledge-v5.mjs, and commit its output as the final commit again.

Evidence

  • Failure before the change: on main, packages/native/specs/swift/library/*.md have no frontmatter, and check:knowledge passes. On this branch, the same files at their old paths each fail with an INV27 message (covered in check-knowledge.test.mjs).
  • Success after the change: node scripts/check-knowledge.mjs and --base origin/main print "Knowledge templates and records are aligned."
  • Product/runtime behavior verified unchanged: only knowledge tooling, schemas, templates, records, and native spec Markdown change. No package source or published output changes.

Scope

Writing rubric results

The converted native records keep the approved text; only section names, frontmatter, and cross-references changed. The rubric was run over the added sections and the AST-093 bullet:

  • R1 narration: none. The added System model, Change coupling, and Owning code describe the system in the present tense.
  • R2 research in the record: none.
  • R3 evidence naming a change: none.
  • R4 rejected alternatives: none added.
  • R5 pull request or issue references: none.
  • R6 ruled open questions still listing options: none added. The records' existing open questions are unchanged.

Since the last review

  • The native conversion is split out to docs(native): every Swift shared rule is an architecture record #8500.
  • scripts/migrate-knowledge-v5.mjs lists records as check:knowledge discovers them, tracked and untracked but not ignored, so a new record the check flags is migrated before it's staged. There's a test for it.
  • validatePlatformComponentRecord requires a platform record to sit where core keeps its component: the core record's folder, the core <Name>/ directory, or the folder of <Name>.doc.mjs (AST-093 FR1 with spec(AST-093): a native component lives in the folder where core keeps it (FR1) #8593). Tests: Avatar/AvatarStatusDot and List/ListItem pass; ListItem/ListItem, Card/ListItem and Icon/Banner fail, each naming the right folder.
    • pnpm specs:for routes a platform member record (Swift AvatarStatusDot in Avatar/) only to its same-stem files, as core routes a member record. The folder's own component record still covers the whole folder.
  • The native specs READMEs give the member case: a spec sits where core keeps the component (Avatar/AvatarStatusDot.spec.md), following spec(AST-093): a native component lives in the folder where core keeps it (FR1) #8593.
  • migrate-knowledge-v5.mjs skips a tracked record that was moved or deleted but not staged, as check:knowledge does.
  • Rebased on today's main and the migration rerun: 146 component records, including the new Blockquote record.

Testing

  • pnpm vitest run --project node scripts/check-knowledge.test.mjs scripts/specs-for-file.test.mjs .github/scripts/knowledge-paths.test.mjs .github/scripts/change-scope.test.mjs .github/scripts/spec-owner-decision.test.mjs .github/scripts/spec-owner-reconcile.test.mjs .github/scripts/spec-owner-workflow.test.mjs: 8 files, 424 tests pass, including scripts/migrate-knowledge-v5.test.mjs. New cases cover INV27 candidates, package-record ids, platform records (path id, platform_of with and without a core record, the anatomy map, a spec outside the Swift component tree), specs:for routing through platform_of, and change-scope.
  • node scripts/check-knowledge.mjs and node scripts/check-knowledge.mjs --base origin/main: aligned. node scripts/migrate-knowledge-v5.mjs --check: every component record is on schema v5.

@vercel

vercel Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 27, 2026 5:01am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Oct 27, 2026, 5:41 AM UTC

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 24, 2026
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 24, 2026
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

Component Size

Component Import before Import after Delta CSS before CSS after Delta
core/AlertDialog 56.9KB 56.9KB 0B 12.4KB 12.4KB 0B
core/AppShell 57.9KB 57.9KB 0B 11.6KB 11.6KB 0B
core/AspectRatio 3.7KB 3.7KB 0B 3.5KB 3.5KB 0B
core/Avatar 37.5KB 37.5KB 0B 6.3KB 6.3KB 0B
core/AvatarGroup 39.8KB 39.8KB 0B 6.4KB 6.4KB 0B
core/AvatarGroupOverflow 39.9KB 39.9KB 0B 6.4KB 6.4KB 0B
core/AvatarStatusDot 7.1KB 7.1KB 0B 3.4KB 3.4KB 0B
core/Badge 3.9KB 3.9KB 0B 3.8KB 3.8KB 0B
core/Banner 47.8KB 47.8KB 0B 9.9KB 9.9KB 0B
core/BaseTypeahead 54.3KB 54.3KB 0B 9.9KB 9.9KB 0B
core/Blockquote 3.5KB 3.5KB 0B 3.4KB 3.4KB 0B
core/BottomSheet 34.0KB 34.0KB 0B 7.9KB 7.9KB 0B
core/BottomSheetSwitcher 14.8KB 14.8KB 0B 3.3KB 3.3KB 0B
core/BreadcrumbItem 66.4KB 66.4KB 0B 11.0KB 11.0KB 0B
core/Breadcrumbs 22.4KB 22.4KB 0B 3.3KB 3.3KB 0B
core/Button 43.3KB 43.3KB 0B 9.2KB 9.2KB 0B
core/ButtonGroup 8.4KB 8.4KB 0B 3.3KB 3.3KB 0B
core/Calendar 54.9KB 54.9KB 0B 10.0KB 10.0KB 0B
core/Carousel 50.2KB 50.2KB 0B 10.2KB 10.2KB 0B
core/Center 4.2KB 4.2KB 0B 4.6KB 4.6KB 0B
core/ChatComposer 60.6KB 60.6KB 0B 10.8KB 10.8KB 0B
core/ChatComposerDrawer 23.9KB 23.9KB 0B 4.5KB 4.5KB 0B
core/ChatComposerInput 55.7KB 55.7KB 0B 10.1KB 10.1KB 0B
core/ChatComposerTokenElement 55.7KB 55.7KB 0B 10.1KB 10.1KB 0B
core/ChatDictationButton 46.5KB 46.5KB 0B 9.5KB 9.5KB 0B
core/ChatLayout 48.8KB 48.8KB 0B 9.9KB 9.9KB 0B
core/ChatLayoutScrollButton 46.4KB 46.4KB 0B 9.6KB 9.6KB 0B
core/ChatMessage 23.1KB 23.1KB 0B 3.5KB 3.5KB 0B
core/ChatMessageBubble 7.0KB 7.0KB 0B 3.6KB 3.6KB 0B
core/ChatMessageList 28.9KB 28.9KB 0B 7.8KB 7.8KB 0B
core/ChatMessageMetadata 25.8KB 25.8KB 0B 3.9KB 3.9KB 0B
core/ChatSendButton 45.8KB 45.8KB 0B 9.2KB 9.2KB 0B
core/ChatSystemMessage 6.7KB 6.7KB 0B 3.7KB 3.7KB 0B
core/ChatTokenizedText 6.9KB 6.9KB 0B 3.9KB 3.9KB 0B
core/ChatToolCalls 31.9KB 31.9KB 0B 8.9KB 8.9KB 0B
core/CheckIndicator 9.0KB 9.0KB 0B 3.6KB 3.6KB 0B
core/CheckboxIndicator 4.1KB 4.1KB 0B 3.8KB 3.8KB 0B
core/CheckboxInput 49.9KB 49.9KB 0B 9.3KB 9.3KB 0B
core/CheckboxList 46.0KB 46.0KB 0B 8.1KB 8.1KB 0B
core/CheckboxListItem 54.0KB 54.0KB 0B 10.5KB 10.5KB 0B
core/Citation 25.9KB 25.9KB 0B 4.1KB 4.1KB 0B
core/ClickableCard 12.8KB 12.8KB 0B 6.9KB 6.9KB 0B
core/Code 3.5KB 3.5KB 0B 3.4KB 3.4KB 0B
core/CodeBlock 60.5KB 60.5KB 0B 10.7KB 10.7KB 0B
core/Collapsible 11.7KB 11.7KB 0B 4.2KB 4.2KB 0B
core/CollapsibleGroup 6.4KB 6.4KB 0B 3.2KB 3.2KB 0B
core/CommandPalette 50.9KB 50.9KB 0B 11.8KB 11.8KB 0B
core/CommandPaletteEmpty 6.1KB 6.1KB 0B 3.3KB 3.3KB 0B
core/CommandPaletteFooter 23.3KB 23.3KB 0B 3.5KB 3.5KB 0B
core/CommandPaletteGroup 3.5KB 3.5KB 0B 3.3KB 3.3KB 0B
core/CommandPaletteInput 32.3KB 32.3KB 0B 8.1KB 8.1KB 0B
core/CommandPaletteItem 8.4KB 8.4KB 0B 3.5KB 3.5KB 0B
core/CommandPaletteList 22.4KB 22.4KB 0B 3.3KB 3.3KB 0B
core/ComplexSelector 55.8KB 55.8KB 0B 10.6KB 10.6KB 0B
core/ContextMenu 77.7KB 77.7KB 0B 14.6KB 14.6KB 0B
core/ContextMenuItem 16.6KB 16.6KB 0B 5.2KB 5.2KB 0B
core/DateInput 99.9KB 99.9KB 0B 14.8KB 14.8KB 0B
core/DateRangeInput 69.4KB 69.4KB 0B 11.2KB 11.2KB 0B
core/DateTimeInput 110.1KB 110.1KB 0B 15.2KB 15.2KB 0B
core/Dialog 16.2KB 16.2KB 0B 7.1KB 7.1KB 0B
core/DialogHeader 48.8KB 48.8KB 0B 9.8KB 9.8KB 0B
core/Divider 6.5KB 6.5KB 0B 3.6KB 3.6KB 0B
core/Drawer 31.6KB 31.6KB 0B 8.0KB 8.0KB 0B
core/DrawerHeader 48.9KB 48.9KB 0B 11.2KB 11.2KB 0B
core/DropdownMenu 72.7KB 72.7KB 0B 14.7KB 14.7KB 0B
core/DropdownMenuCheckboxItem 16.1KB 16.1KB 0B 5.6KB 5.6KB 0B
core/DropdownMenuDivider 6.6KB 6.6KB 0B 3.6KB 3.6KB 0B
core/DropdownMenuGroup 6.1KB 6.1KB 0B 3.3KB 3.3KB 0B
core/DropdownMenuItem 15.4KB 15.4KB 0B 5.2KB 5.2KB 0B
core/DropdownMenuRadioGroup 6.0KB 6.0KB 0B 3.2KB 3.2KB 0B
core/DropdownMenuRadioItem 16.2KB 16.2KB 0B 5.6KB 5.6KB 0B
core/DropdownMenuSubMenu 58.1KB 58.1KB 0B 9.5KB 9.5KB 0B
core/EmptyState 7.7KB 7.7KB 0B 3.5KB 3.5KB 0B
core/Field 44.2KB 44.2KB 0B 8.0KB 8.0KB 0B
core/FieldLabel 39.8KB 39.8KB 0B 6.5KB 6.5KB 0B
core/FieldStatus 10.4KB 10.4KB 0B 4.2KB 4.2KB 0B
core/FileInput 54.1KB 54.1KB 0B 10.3KB 10.3KB 0B
core/FormLayout 6.3KB 6.3KB 0B 3.4KB 3.4KB 0B
core/Grid 4.3KB 4.3KB 0B 3.7KB 3.7KB 0B
core/GridSpan 3.4KB 3.4KB 0B 3.2KB 3.2KB 0B
core/Icon 8.8KB 8.8KB 0B 3.6KB 3.6KB 0B
core/IconButton 43.3KB 43.3KB 0B 9.2KB 9.2KB 0B
core/Item 11.4KB 11.4KB 0B 4.7KB 4.7KB 0B
core/Kbd 6.7KB 6.7KB 0B 3.5KB 3.5KB 0B
core/Layout 8.1KB 8.1KB 0B 5.5KB 5.5KB 0B
core/LayoutContent 7.4KB 7.4KB 0B 4.9KB 4.9KB 0B
core/LayoutFooter 7.3KB 7.3KB 0B 4.8KB 4.8KB 0B
core/LayoutHeader 7.4KB 7.4KB 0B 4.8KB 4.8KB 0B
core/LayoutPanel 7.6KB 7.6KB 0B 4.8KB 4.8KB 0B
core/Lightbox 51.2KB 51.2KB 0B 9.8KB 9.8KB 0B
core/Link 43.5KB 43.5KB 0B 7.6KB 7.6KB 0B
core/LinkProvider 3.5KB 3.5KB 0B 20B 20B 0B
core/List 6.7KB 6.7KB 0B 3.4KB 3.4KB 0B
core/ListItem 53.5KB 53.5KB 0B 10.5KB 10.5KB 0B
core/Markdown 144.5KB 144.5KB 0B 17.4KB 17.4KB 0B
core/MobileNav 51.0KB 51.0KB 0B 10.1KB 10.1KB 0B
core/MobileNavToggle 46.2KB 46.2KB 0B 9.4KB 9.4KB 0B
core/MoreMenu 72.9KB 72.9KB 0B 14.7KB 14.7KB 0B
core/MultiSelector 76.2KB 76.2KB 0B 14.6KB 14.6KB 0B
core/NavHeadingMenu 8.9KB 8.9KB 0B 3.2KB 3.2KB 0B
core/NavIcon 3.4KB 3.4KB 0B 3.3KB 3.3KB 0B
core/NumberInput 55.7KB 55.7KB 0B 10.7KB 10.7KB 0B
core/Outline 28.6KB 28.6KB 0B 4.0KB 4.0KB 0B
core/OverflowList 8.5KB 8.5KB 0B 3.5KB 3.5KB 0B
core/Overlay 19.5KB 19.5KB 0B 3.8KB 3.8KB 0B
core/Pagination 87.7KB 87.7KB 0B 15.3KB 15.3KB 0B
core/Popover 49.8KB 49.8KB 0B 12.1KB 12.1KB 0B
core/PowerSearch 155.1KB 155.1KB 0B 18.6KB 18.6KB 0B
core/ProgressBar 7.7KB 7.7KB 0B 6.6KB 6.6KB 0B
core/RadioIndicator 3.8KB 3.8KB 0B 3.7KB 3.7KB 0B
core/ResizeHandle 25.1KB 25.1KB 0B 3.9KB 3.9KB 0B
core/ScrollableArea 10.4KB 10.4KB 0B 4.3KB 4.3KB 0B
core/Section 7.5KB 7.5KB 0B 6.2KB 6.2KB 0B
core/SegmentedControl 38.8KB 38.8KB 0B 6.3KB 6.3KB 0B
core/SegmentedControlItem 8.6KB 8.6KB 0B 3.9KB 3.9KB 0B
core/Selector 79.1KB 79.1KB 0B 15.0KB 15.0KB 0B
core/SelectorOption 14.5KB 14.5KB 0B 5.1KB 5.1KB 0B
core/SideNav 58.0KB 58.0KB 0B 10.6KB 10.6KB 0B
core/SideNavCollapseButton 46.6KB 46.6KB 0B 9.5KB 9.5KB 0B
core/SideNavHeading 54.7KB 54.7KB 0B 10.1KB 10.1KB 0B
core/SideNavItem 54.4KB 54.4KB 0B 10.1KB 10.1KB 0B
core/SideNavSection 6.5KB 6.5KB 0B 3.6KB 3.6KB 0B
core/Skeleton 3.8KB 3.8KB 0B 3.6KB 3.6KB 0B
core/Slider 48.5KB 48.5KB 0B 8.5KB 8.5KB 0B
core/Spinner 26.3KB 26.3KB 0B 7.5KB 7.5KB 0B
core/Stack 7.1KB 7.1KB 0B 4.9KB 4.9KB 0B
core/StackItem 6.0KB 6.0KB 0B 3.3KB 3.3KB 0B
core/StatusDot 19.0KB 19.0KB 0B 6.2KB 6.2KB 0B
core/Step 32.4KB 32.4KB 0B 5.3KB 5.3KB 0B
core/Stepper 47.4KB 47.4KB 0B 9.6KB 9.6KB 0B
core/Switch 48.4KB 48.4KB 0B 9.3KB 9.3KB 0B
core/Tab 9.7KB 9.7KB 0B 4.1KB 4.1KB 0B
core/TabList 40.2KB 40.2KB 0B 7.2KB 7.2KB 0B
core/TabMenu 51.6KB 51.6KB 0B 10.0KB 10.0KB 0B
core/Table 84.0KB 84.0KB 0B 15.1KB 15.1KB 0B
core/TableBody 3.3KB 3.3KB 0B 3.2KB 3.2KB 0B
core/TableCell 78.8KB 78.8KB 0B 14.8KB 14.8KB 0B
core/TableFooter 3.3KB 3.3KB 0B 3.2KB 3.2KB 0B
core/TableHeader 3.3KB 3.3KB 0B 3.2KB 3.2KB 0B
core/TableHeaderCell 78.6KB 78.6KB 0B 14.8KB 14.8KB 0B
core/TableRow 6.2KB 6.2KB 0B 3.5KB 3.5KB 0B
core/TableSelectionToolbar 52.4KB 52.4KB 0B 11.2KB 11.2KB 0B
core/Text 8.6KB 8.6KB 0B 6.8KB 6.8KB 0B
core/TextArea 49.4KB 49.4KB 0B 9.4KB 9.4KB 0B
core/TextInput 53.5KB 53.5KB 0B 10.5KB 10.5KB 0B
core/Thumbnail 50.7KB 50.7KB 0B 11.0KB 11.0KB 0B
core/Timer 9.2KB 9.2KB 0B 6.8KB 6.8KB 0B
core/ToggleButton 44.1KB 44.1KB 0B 9.3KB 9.3KB 0B
core/ToggleButtonGroup 6.3KB 6.3KB 0B 3.2KB 3.2KB 0B
core/Token 29.6KB 29.6KB 0B 4.5KB 4.5KB 0B
core/Tokenizer 64.8KB 64.8KB 0B 11.7KB 11.7KB 0B
core/Toolbar 39.8KB 39.8KB 0B 7.7KB 7.7KB 0B
core/Tooltip 16.8KB 16.8KB 0B 4.9KB 4.9KB 0B
core/TopNav 51.9KB 51.9KB 0B 10.4KB 10.4KB 0B
core/TopNavHeading 54.2KB 54.2KB 0B 9.9KB 9.9KB 0B
core/TopNavItem 9.0KB 9.0KB 0B 3.8KB 3.8KB 0B
core/TopNavMegaMenu 54.2KB 54.2KB 0B 10.8KB 10.8KB 0B
core/TopNavMegaMenuFeaturedCard 6.7KB 6.7KB 0B 3.4KB 3.4KB 0B
core/TopNavMegaMenuItem 9.1KB 9.1KB 0B 4.1KB 4.1KB 0B
core/TopNavMenu 53.6KB 53.6KB 0B 10.1KB 10.1KB 0B
core/TreeList 32.5KB 32.5KB 0B 4.7KB 4.7KB 0B
core/Typeahead 61.5KB 61.5KB 0B 11.3KB 11.3KB 0B
core/TypeaheadItem 6.2KB 6.2KB 0B 3.4KB 3.4KB 0B
lab/CommentPin 47.4KB 47.4KB 0B 1.2KB 1.2KB 0B
lab/Schedule 65.6KB 65.6KB 0B 3.9KB 3.9KB 0B

Sizes are gzip. Import counts the JavaScript the import loads eagerly; CSS counts the package stylesheet rules referenced by the modules it can load from its own package, lazily loaded ones included.

Bundle Size Summary

Gzip figures measure each package's entry file, not the code an import pulls in.

Package Entry (ESM) Entry gzip before Entry gzip after Delta
@astryxdesign/core 4.9KB 1.2KB 1.2KB 0B
@astryxdesign/lab 4.6KB 1.9KB 1.9KB 0B
@astryxdesign/charts 922B 436B 436B 0B
Package stylesheet Gzip before Gzip after Delta
@astryxdesign/core 34.6KB 34.6KB 0B
@astryxdesign/lab 11.1KB 11.1KB 0B
@astryxdesign/charts 631B 631B 0B

Accessibility Audit

Status: No accessibility violations detected.

Visual Regression

55 of 502 shot(s) changed.

A change here is a question, not a failure: check whether the after is the
picture you intended. Record that review on the PR. Baseline maintenance is an
explicit dispatch of CI; this report never rewrites the baseline or adds a release gate.

component story theme mode pixels
Selector Indicator Space Bottom Sheet Narrow End RTL neutral light 753,933
Selector Indicator Space Bottom Sheet Wide Start neutral light 740,072
RichTextEditor Markdown parity: side by side probe dark 558,840
RichTextEditor Markdown parity: side by side probe light 540,756
Chat Full AI Chat probe light 230,823
Chat Full AI Chat probe dark 229,805
AppShell With Mobile Nav probe light 217,010
AppShell With Mobile Nav probe dark 216,960
Collapsible Dividers probe dark 66,445
Collapsible Dividers probe light 66,445
AppShell Playground neutral dark 65,198
AppShell Playground neutral light 63,788
Chat Default neutral dark 36,304
Chat Default neutral light 35,767
Chat Empty State probe light 23,531
Chat Empty State probe dark 22,622
ChatAutoScroll Scroll Behavior Comparison neutral dark 15,378
ChatAutoScroll Scroll Behavior Comparison neutral light 14,107
Chat With Attachments probe light 13,406
Chat With Attachments probe dark 11,232

and 35 more.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on an engineering owner deciding whether the seven Swift rule records in packages/native/specs/swift/ should land as authority: current: their sources on main say Status: draft, and no approval covers this head yet. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so if they are an engineering owner; otherwise the records can land as authority: draft. Either way, these record fixes are needed:

  • theme-generator.spec.md G3 still requires swift-ios-1/core/Theme/Generated/ paths, which contradicts AST-093 FR1 and the record's own Owning code (packages/native/apple/Sources/Astryx/).
  • The Current-state notes in styles, theme-environment, component-api and theme-generator say the Swift views, theme and generator do not exist yet.
  • accessibility.spec.md calls itself Draft in its Contract-at-a-glance table, and packages/native/apple/README.md still links the deleted library/theme-generator.md.

The test-node (1/4) failure is the watch-mode case in build-theme.icons-specifier.test.mjs, outside this change, and it passes when run on its own at this head.

[Automated review]

## Owning code

- `packages/native/scripts/` — the theme generator and its drift check.
- `packages/native/apple/Sources/Astryx/` — the generated Swift themes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This names packages/native/apple/Sources/Astryx/ for the generated themes, but G3 (lines 65 and 73) still requires swift-ios-1/core/Theme/Generated/Tokens.swift and swift-ios-1/core/Theme/Generated/<SwiftName>Theme.swift. AST-093 FR1 puts Swift in packages/native/apple/, and the generator's SWIFT_THEME_DIR is apple/Sources/Astryx/Theme/Generated/, so G3's two paths need updating before this record is current.

| System behavior | Name, role, state, and value come from the core contract; disabled controls stay reachable; covered messages announce once after load; every setting in X6 is honored. |
| End-user impact | A VoiceOver user on iPhone hears the same name, role, state, and messages as a screen-reader user on the web; people using Reduce Motion, Bold Text, and the other settings get them honored. |
| Builder impact | A Swift component author maps the core contract to SwiftUI accessibility APIs by these rules instead of deciding them per component. |
| Compatibility/readiness | Draft. No Swift component yet has accessibility tests or an audit. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The frontmatter says authority: current, but this projection says "Draft." The template uses this cell for the record's authority and implementation state, so it should say current, keeping the note that no Swift component has accessibility tests or an audit yet.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on an engineering owner deciding whether the seven Swift rule records in packages/native/specs/swift/ land as authority: current: their sources on main say Status: draft, and no approval covers this head. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so if they are an engineering owner; otherwise the records can land as authority: draft, and since the branch now conflicts with main in packages/native/apple/Sources/Astryx/Icon/Icon.spec.md, the decision belongs on the rebased head. Either way, these fixes are needed:

  • validatePlatformComponentRecord accepts a Swift record saved in another component's folder (for example Icon/Banner.spec.md); require the folder to match the record's name, as Core and Lab records already must.
  • The Current-state notes in styles.spec.md, theme-environment.spec.md and slots.spec.md say the Swift views, theme and icon slot do not exist.
  • accessibility.spec.md still calls itself Draft in its Contract-at-a-glance table, and the Swift README's "the record wins" sentence ranks these records below every other record.

[Automated review]

* keeps the shared contract; until it has one, the core component's public
* source and documentation (`packages/core/src/<PublicName>/`) stand in.
*/
function validatePlatformComponentRecord(root, record, location, recordsById) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This derives the id and platform_of from the file name only, and the platform branch at line 1019 skips the root check that Core and Lab records get at line 1057. On this head packages/native/apple/Sources/Astryx/Icon/Banner.spec.md (id component:swift/Banner, platform_of: component:Banner) passes check:knowledge, and specs:for then routes the Icon folder's files to Banner's records. The knowledge-contracts Owning code counts the platform component directories as component roots, where "the public name normally matches the root", and AST-093 FR1 gives each native component a folder named for it. Requiring location.publicName === location.componentRoot here, with a test beside the other DEC-13 cases, closes it.

Comment thread packages/native/specs/swift/README.md Outdated
Rules shared by every Astryx component written in Swift, for iOS and macOS, as
architecture records (`architecture:native-swift-<slug>`), one concern per
file. A component spec follows these and records only where its component
differs. Where one of them and an approved record disagree, the record wins.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that these files are architecture records, "Where one of them and an approved record disagree, the record wins" gives every other approved record precedence over them once they are current, which knowledge-contracts INV9 rules out ("A newer, narrower, or more local current record does not silently override another current record"). Dropping the sentence, or naming the records that win (AST-082 and AST-093, as AST-093 FR1 does), keeps the README consistent.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on an engineering owner deciding whether the seven Swift rule records in packages/native/specs/swift/ land as authority: current: their sources on main say Status: draft, and no approval covers this head. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so if they are an engineering owner; otherwise the records can land as authority: draft, and since a new commit makes an approval stale, the decision belongs on the head that carries the fixes below. These fixes are needed:

  • validatePlatformComponentRecord accepts a Swift record saved in another component's folder (for example Icon/Banner.spec.md); require the folder to match the record's name, as Core and Lab records already must.
  • Before the records are current: the Current-state notes in styles.spec.md, theme-environment.spec.md and slots.spec.md say the Swift views, theme and icon slot do not exist, accessibility.spec.md calls itself Draft in its Contract-at-a-glance table, and the Swift README's "the record wins" sentence ranks these records below every other record.

[Automated review]

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on two engineering-owner decisions: whether the seven Swift rule records in packages/native/specs/swift/ land as authority: current (their sources on main say Status: draft, and no approval covers this head or #8500's), and whether AST-093 FR1 places a member component's Swift record in the folder where core keeps it, as this checker requires (#8593 covers members that have a core record, not ones like ListItem that core documents only through a .doc.mjs). An engineering owner records each decision by commenting /approve-spec <full head SHA> on the pull request that lands that spec text, and the author may do so as an engineering owner; otherwise the records land as authority: draft and the checker accepts each component's own folder. Two changes are needed whichever way those decisions go, and a third if family folders are approved:

  • Land #8500 first and rebase this branch without its commit: at 2,143 authored lines, this head is over the 2,000-line limit.
  • scripts/migrate-knowledge-v5.mjs crashes with ENOENT when a tracked *.spec.md has been moved or deleted but not staged; skip paths that no longer exist, as check:knowledge does.
  • pnpm specs:for sends every file in Sources/Astryx/Avatar/ to AvatarStatusDot's records as well; route a member's record only to its own same-stem files, as core does.

[Automated review]

Comment on lines +264 to +274
if (record.platform) {
const platformRoot = `${record.platform.componentTree}/${record.platform.componentRoot}/`;
if (filePath.startsWith(platformRoot)) {
matches.push({
record,
via: 'placement',
detail: `platform component record for ${platformRoot}`,
});
}
continue;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches a platform record to every file in its folder, so with the Swift AvatarStatusDot record in Avatar/, pnpm specs:for --include-draft packages/native/apple/Sources/Astryx/Avatar/Avatar.swift also lists component:swift/AvatarStatusDot, core's component:AvatarStatusDot through platform_of, and the records only AvatarStatusDot inherits. Core routes Avatar.tsx to component:Avatar alone, because a member record matches only its same-stem files (lines 305-320). Applying the same rule here, a record whose name matches its folder covering the folder and a member covering only its same-stem files, keeps Swift lookups in line with core.

Comment on lines +71 to +73
for (const filePath of new Set(specRecordFiles(ROOT))) {
const absolute = path.join(ROOT, filePath);
const migrated = migrateComponentRecord(fs.readFileSync(absolute, 'utf8'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git ls-files --cached --others still lists a tracked *.spec.md that was moved or deleted without staging, so this read throws ENOENT. For example, moving the Swift AvatarStatusDot record into AvatarStatusDot/ with a plain mv, or deleting packages/core/src/Kbd/Kbd.spec.md before git rm, makes both --check and a plain run exit 1 with a stack trace. check:knowledge filters these paths with fs.existsSync (scripts/check-knowledge.mjs:727-730); the same filter in specRecordFiles, with a test beside the untracked-file case, keeps the two in step.

Comment on lines +957 to +965
if (!coreFolders.has(location.componentRoot)) {
const places = [...coreFolders]
.sort()
.map(folder => `${location.componentTree}/${folder}/`)
.join(' or ');
problems.push(
`${record.filePath}: a platform component record lives in the folder where core keeps its component: ${location.publicName}.spec.md belongs in ${places}.`,
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the 80 core names without their own packages/core/src/<Name>/ folder, this refuses Sources/Astryx/<Name>/<Name>.spec.md, the path AST-093 FR1 gives every native component. Whether family folders are allowed is an engineering-owner decision on FR1. #8593's proposed sentence covers the 48 members that have a core record in another folder (AvatarStatusDot), but not the 32 that core documents only through a .doc.mjs, such as ListItem in List/, which this check also places by their doc's folder.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on two engineering-owner decisions: whether the seven Swift rule records in packages/native/specs/swift/ land as authority: current (their sources on main say Status: draft, and no approval covers this head or #8500's), and whether AST-093 FR1 is amended so a member component's Swift record sits in the folder where core keeps it, as this checker requires (#8593 proposes that amendment and is not yet approved). An engineering owner records each decision by commenting /approve-spec <full head SHA> on the pull request that lands that spec text, and the author may do so as an engineering owner; otherwise the records land as authority: draft and the checker accepts each component's own folder. One change is needed whichever way those decisions go, and one more if family folders are approved:

  • Land #8500 first and rebase this branch without its commit: at 2,208 authored lines, this head is over the 2,000-line limit.
  • packages/native/specs/README.md and packages/native/specs/swift/README.md still give every component Sources/Astryx/<Name>/<Name>.spec.md, so they need the member case if family folders are approved.

[Automated review]

Comment thread packages/native/specs/README.md Outdated
Comment on lines +9 to +11
- **A native component's spec** sits in the component's own folder beside its
implementation, the way core keeps `TabList.spec.md` next to `TabList.tsx`:
`packages/native/apple/Sources/Astryx/<Name>/<Name>.spec.md`. It is a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gives every native component Sources/Astryx/<Name>/<Name>.spec.md, but scripts/check-knowledge.mjs:954-965 refuses that path for a member core keeps in another folder: with the Swift AvatarStatusDot record moved to AvatarStatusDot/, the check says it "belongs in packages/native/apple/Sources/Astryx/Avatar/", and ListItem/ListItem.spec.md is refused in favour of List/. If the AST-093 FR1 amendment in #8593 is approved, this bullet and packages/native/specs/swift/README.md:20-21 need the member case; if it is not, the checker should accept the own folder instead.

@cixzhang
cixzhang force-pushed the feat/knowledge-records-everywhere branch from 27f006c to 93c9740 Compare October 27, 2026 04:48

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on two engineering-owner decisions. The first is whether the seven Swift rule records in packages/native/specs/swift/ land as authority: current: their sources on main say Status: draft, and no approval covers this head or #8500's. The second is whether AST-093 FR1 is amended so a member component's Swift record sits in the folder where core keeps it, as this checker requires (#8593 proposes that amendment and is not yet approved). An engineering owner, the author included, records each decision by commenting /approve-spec <full head SHA> on the pull request that lands that spec text; otherwise the records land as authority: draft and the checker accepts each component's own folder.

  • Whichever way those go, land #8500 first and rebase this branch without its commit: at 2,208 authored lines, this head is over the 2,000-line limit.

[Automated review]

This branch was successfully deployed

1 active deployment
Preview — fb53f32e Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. needs:spec-owner-review Current knowledge records await owner approval

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant