diff --git a/.changeset/wave-1-reliability.md b/.changeset/wave-1-reliability.md new file mode 100644 index 0000000..5ec28a2 --- /dev/null +++ b/.changeset/wave-1-reliability.md @@ -0,0 +1,8 @@ +--- +"@nexcraft/forge": minor +"@nexcraft/forge-rhf": patch +"@nexcraft/forge-tokens": patch +"@nexcraft/forge-mcp-figma": patch +--- + +Reliability release: six verified component bug fixes (select ARIA + update-loop, multi-select regex crash, form-field aria-describedby, tree-view selected/disabled styling, button ghost/link variants, icon SVG sanitization), elimination of Lit change-in-update warnings across eight components, tooltip htmlContent sanitization, removal of unimplemented data-grid feature surface, honest README/docs claims with dead links fixed, MIT license metadata for forge-tokens and forge-mcp-figma, forge-rhf no longer bundles forge-react, and vitest updated to 3.2.6 (GHSA-5xrq-8626-4rwp). diff --git a/.cursorrules b/.cursorrules index 9524251..05a069e 100644 --- a/.cursorrules +++ b/.cursorrules @@ -4,17 +4,17 @@ - Package: @nexcraft/forge - Description: AI-native web component library with React/Vue/Angular integrations - Repository: https://github.com/dev-ignis/forge -- Documentation: ./docs/ai-methods.md +- Documentation: ./docs/ai/metadata-reference.md ## Import Preferences ### React Projects (Recommended) ```javascript // Prefer React integrations for better TypeScript support and SSR -import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge/integrations/react' +import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge-react' // For forms with validation -import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge-rhf' ``` ### Tree-shaking / Bundle Optimization @@ -105,7 +105,7 @@ forge-button { ### React + TypeScript ```typescript -import { ForgeButton } from '@nexcraft/forge/integrations/react' +import { ForgeButton } from '@nexcraft/forge-react' interface Props { onSubmit: () => void @@ -128,7 +128,7 @@ function SubmitButton({ onSubmit, loading }: Props) { ### React Hook Form ```javascript import { useForm } from 'react-hook-form' -import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge-rhf' function UserForm() { const { control, handleSubmit } = useForm() @@ -155,7 +155,7 @@ function UserForm() { ### Next.js SSR ```javascript // Components work with SSR out of the box -import { ForgeCard, ForgeButton } from '@nexcraft/forge/integrations/react' +import { ForgeCard, ForgeButton } from '@nexcraft/forge-react' export default function Page() { return ( @@ -211,10 +211,6 @@ console.log(`Available: ${aiIndex.summary.totalComponents} components`) // Detailed component specifications import aiManifest from '@nexcraft/forge/ai-manifest.json' console.log(aiManifest.components[0]) // Full component details - -// Framework-specific schemas -import buttonSpec from '@nexcraft/forge/ai-tools/react/button.json' -import vanillaSpec from '@nexcraft/forge/ai-tools/vanilla/button.json' ``` ### AI Method Usage @@ -238,9 +234,7 @@ const aiState = button.aiState ## Documentation Links - **AI Index**: ./ai-index.json (quick component discovery) - **AI Manifest**: ./ai-manifest.json (detailed specifications) -- **AI Tools**: ./ai-tools/ (framework-specific schemas) -- AI Methods Guide: ./docs/ai-methods.md -- Common Patterns: ./docs/patterns/AI_COMMON_PATTERNS.md +- AI Methods Guide: ./docs/ai/metadata-reference.md - Import Guide: ./docs/guides/AI_IMPORT_GUIDE.md ## Avoid These Patterns diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9c08753..fa7010a 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -4,17 +4,17 @@ - Package: @nexcraft/forge - Description: AI-native web component library with React/Vue/Angular integrations - Repository: https://github.com/dev-ignis/forge -- Documentation: ./docs/ai-methods.md +- Documentation: ./docs/ai/metadata-reference.md ## Import Preferences ### React Projects (Recommended) ```javascript // Prefer React integrations for better TypeScript support and SSR -import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge/integrations/react' +import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge-react' // For forms with validation -import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge-rhf' ``` ### Tree-shaking / Bundle Optimization @@ -105,7 +105,7 @@ forge-button { ### React + TypeScript ```typescript -import { ForgeButton } from '@nexcraft/forge/integrations/react' +import { ForgeButton } from '@nexcraft/forge-react' interface Props { onSubmit: () => void @@ -128,7 +128,7 @@ function SubmitButton({ onSubmit, loading }: Props) { ### React Hook Form ```javascript import { useForm } from 'react-hook-form' -import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge-rhf' function UserForm() { const { control, handleSubmit } = useForm() @@ -155,7 +155,7 @@ function UserForm() { ### Next.js SSR ```javascript // Components work with SSR out of the box -import { ForgeCard, ForgeButton } from '@nexcraft/forge/integrations/react' +import { ForgeCard, ForgeButton } from '@nexcraft/forge-react' export default function Page() { return ( @@ -211,10 +211,6 @@ console.log(`Available: ${aiIndex.summary.totalComponents} components`) // Detailed component specifications import aiManifest from '@nexcraft/forge/ai-manifest.json' console.log(aiManifest.components[0]) // Full component details - -// Framework-specific schemas -import buttonSpec from '@nexcraft/forge/ai-tools/react/button.json' -import vanillaSpec from '@nexcraft/forge/ai-tools/vanilla/button.json' ``` ### AI Method Usage @@ -238,9 +234,7 @@ const aiState = button.aiState ## Documentation Links - **AI Index**: ./ai-index.json (quick component discovery) - **AI Manifest**: ./ai-manifest.json (detailed specifications) -- **AI Tools**: ./ai-tools/ (framework-specific schemas) -- AI Methods Guide: ./docs/ai-methods.md -- Common Patterns: ./docs/patterns/AI_COMMON_PATTERNS.md +- AI Methods Guide: ./docs/ai/metadata-reference.md - Import Guide: ./docs/guides/AI_IMPORT_GUIDE.md ## Avoid These Patterns diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5984d01..4b8247f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,6 +3,7 @@ updates: # npm (workspace root) - package-ecosystem: "npm" directory: "/" + target-branch: "develop" schedule: interval: "weekly" day: "monday" @@ -29,11 +30,12 @@ updates: commit-message: prefix: "deps" include: "scope" - labels: ["deps", "security"] + labels: ["deps"] # GitHub Actions - package-ecosystem: "github-actions" directory: "/" + target-branch: "develop" schedule: interval: "weekly" day: "monday" @@ -42,5 +44,5 @@ updates: groups: actions-weekly: patterns: ["*"] - labels: ["deps", "security"] + labels: ["deps"] diff --git a/.github/workflows/auto-label.yml b/.github/workflows/auto-label.yml index 6daf79c..19ce2af 100644 --- a/.github/workflows/auto-label.yml +++ b/.github/workflows/auto-label.yml @@ -41,13 +41,15 @@ jobs: - name: Label WIP if: github.event.pull_request.draft == true - run: gh pr edit ${{ github.event.pull_request.number }} --add-label "status: wip" + run: | + gh pr edit ${{ github.event.pull_request.number }} --add-label "status: wip" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Remove WIP when ready if: github.event.pull_request.draft == false - run: gh pr edit ${{ github.event.pull_request.number }} --remove-label "status: wip" || true + run: | + gh pr edit ${{ github.event.pull_request.number }} --remove-label "status: wip" || true env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 0000000..3d7dd6a --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,23 @@ +name: Check Markdown Links + +on: + pull_request: + paths: + - '**/*.md' + +permissions: + contents: read + +jobs: + lychee: + name: Lychee Link Check + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Link Checker + uses: lycheeverse/lychee-action@v2 + with: + args: --offline --no-progress ./docs README.md + fail: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 5299025..cb83969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,36 +101,6 @@ import { ForgeAvatar } from '@nexcraft/forge/avatar'; ``` -### Patch Changes - -- 7a38d60: Refactor test suite to prevent resource contention and timeouts - - Split tests into fast unit tests (1147 tests) and slow accessibility tests (35 tests) - - Add `test:unit` and `test:a11y` npm scripts for separate execution - - Update `test:coverage` to run both suites sequentially - - Accessibility tests now run in single-fork mode to prevent timeouts - - Coverage maintained at 87% (above 70% threshold) - - All 1182 tests now pass reliably in CI without timeouts - - **Benefits:** - - Faster test execution (unit ~13s, a11y ~3s vs previous 30s+ with timeouts) - - No more flaky accessibility test failures due to resource contention - - Better test organization for future maintenance - -## 0.8.0 - -### Minor Changes - -- 6515991: Phase 15.4: Complete React package extraction and framework separation - - Extract React integration to separate @nexcraft/forge-react package - - Remove all framework integrations from core @nexcraft/forge package - - Update @nexcraft/forge-rhf to use new React package - - Achieve pure web components core architecture - - Set up linked package releases for coordinated versioning - -## 0.9.0 - -### Minor Changes - - **Phase 15 Complete: Framework Integration Package Split** **BREAKING CHANGES**: All framework integrations moved to separate packages @@ -193,10 +163,32 @@ - Framework packages use coordinated beta releases - Automated version bumping based on changeset files +### Patch Changes + +- 7a38d60: Refactor test suite to prevent resource contention and timeouts + - Split tests into fast unit tests (1147 tests) and slow accessibility tests (35 tests) + - Add `test:unit` and `test:a11y` npm scripts for separate execution + - Update `test:coverage` to run both suites sequentially + - Accessibility tests now run in single-fork mode to prevent timeouts + - Coverage maintained at 87% (above 70% threshold) + - All 1182 tests now pass reliably in CI without timeouts + + **Benefits:** + - Faster test execution (unit ~13s, a11y ~3s vs previous 30s+ with timeouts) + - No more flaky accessibility test failures due to resource contention + - Better test organization for future maintenance + ## 0.8.0 ### Minor Changes +- 6515991: Phase 15.4: Complete React package extraction and framework separation + - Extract React integration to separate @nexcraft/forge-react package + - Remove all framework integrations from core @nexcraft/forge package + - Update @nexcraft/forge-rhf to use new React package + - Achieve pure web components core architecture + - Set up linked package releases for coordinated versioning + - **Enhanced AI Discoverability and Documentation System** - Comprehensive AI metadata system for component discovery - Added structured ai-manifest.json with component metadata @@ -317,13 +309,3 @@ - Comprehensive design system tokens - Base architecture with BaseElement and shared utilities - Full testing infrastructure and CI/CD integration - ---- - -## Component Inventory - -**Total: 23+ Production-Ready Components** - -- **Atoms (9)**: Alert, Badge, Button, Checkbox, Icon, Input, Radio Group, Select, Switch -- **Molecules (8)**: Card, DatePicker, Dropdown, FormField, Modal, MultiSelect, Tooltip -- **Organisms (6)**: Accordion, DataTable, NavigationBar, Pagination, Tabs, TreeView diff --git a/README.md b/README.md index 504a1e0..f87f29d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # @nexcraft/forge [![npm version](https://img.shields.io/npm/v/@nexcraft/forge.svg)](https://www.npmjs.com/package/@nexcraft/forge) -[![Bundle Size](https://img.shields.io/badge/bundle%20size-<10KB-brightgreen.svg)](https://bundlephobia.com/package/@nexcraft/forge) -[![Test Coverage](https://img.shields.io/badge/coverage-86.4%25-brightgreen.svg)](./coverage) -[![WCAG 2.1 AA](https://img.shields.io/badge/WCAG%202.1-AA-blue.svg)](https://www.w3.org/WAI/WCAG21/quickref/) +[![Bundle Size](https://img.shields.io/badge/bundle%20size-91KB%20gzip-yellow.svg)](https://bundlephobia.com/package/@nexcraft/forge) +[![Test Coverage](https://img.shields.io/badge/coverage-85.5%25-brightgreen.svg)](#-testing) +[![Accessibility](https://img.shields.io/badge/a11y-organisms%20tested-blue.svg)](https://www.w3.org/WAI/WCAG21/quickref/) [![AI-Native](https://img.shields.io/badge/AI-Native-purple.svg)](./docs/ai/metadata-reference.md) [![Performance Monitored](https://img.shields.io/badge/Performance-Monitored-orange.svg)](./docs/performance-monitoring.md) [![Figma Tokens](https://img.shields.io/badge/Figma%20Tokens-CLI%2FMCP-blue.svg)](./docs/guides/figma-to-forge.md) @@ -15,7 +15,7 @@ ## ๐Ÿค– **FOR AI ASSISTANTS & LLMs** -**AI Context**: @nexcraft/forge is an AI-native web component library with 26+ components and React/Vue/Angular integrations. +**AI Context**: @nexcraft/forge is an AI-native web component library with 30 components (14 atoms, 9 molecules, 7 organisms) and React/Vue/Angular integrations. **Quick AI Reference**: - ๐Ÿ“ฆ **React**: `import { ForgeButton, ForgeInput } from '@nexcraft/forge-react'` @@ -220,7 +220,7 @@ console.log(btn.getPossibleActions()); // AI-ready! ### Development Setup ```bash # Clone and setup -git clone https://github.com/nexcraft/forge.git +git clone https://github.com/dev-ignis/forge.git cd forge npm install @@ -254,18 +254,18 @@ npm install @nexcraft/forge-rhf # + React Hook Form ## ๐Ÿ“‹ Component Index -Quick reference to all 26 components with HTML tag names: +Quick reference to all 30 components with HTML tag names: -### Organisms (6 components) -`` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` +### Organisms (7 components) +`` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` -### Molecules (8 components) -`` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` +### Molecules (9 components) +`` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` -### Atoms (12 components) -`` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` +### Atoms (14 components) +`` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` โ€ข `` -**Plus supporting components**: `` โ€ข `` โ€ข `` +**Plus supporting dev tools**: `` ๐Ÿ’ก **Can't find what you're looking for?** Try searching for keywords like "progress", "toast", "skeleton" in the [Component Showcase](#-components-showcase) section below. @@ -357,7 +357,7 @@ const slowComponents = performanceDashboard.getSlowComponents(16); | **โšก Performance Dashboard** | Real-time visual monitoring + auto-degradation | Self-optimizing components with performance insights | | **๐ŸŒ Framework Independence** | True Web Components | Use with React, Vue, Angular, or vanilla JS | | **๐Ÿ›ก๏ธ Style Isolation** | Shadow DOM guaranteed | Complete style encapsulation, zero CSS conflicts | -| **๐Ÿ“ฆ Optimized Bundle** | <10KB per component | Lightweight, tree-shakeable, production-ready | +| **๐Ÿ“ฆ Bundle Size** | ~91KB gzip (467KB raw) full bundle | Selective imports currently still pull the full bundle; true per-component tree-shaking is on the roadmap | | **๐Ÿ”ฎ Future Proof** | Built on web standards | Will work in browsers for decades to come | ### ๐Ÿš€ **Zero-Config Magic** @@ -417,25 +417,26 @@ Foundation components with comprehensive test coverage: | Component | Test Coverage | Key Features | Documentation | |-----------|--------------|--------------|---------------| -| **Button** | 92.38% | 5 variants, ripple effect, loading states | [๐Ÿ“š Docs](./docs/components/button.md) | -| **Input** | 84.56% | 7 types, validation, clearable | [๐Ÿ“š Docs](./docs/components/input.md) | -| **Icon** | 78.38% | Registry system, lazy loading | [๐Ÿ“š Docs](./docs/components/icon.md) | -| **Alert** | 97.02% | Auto-dismiss, animations | [๐Ÿ“š Docs](./docs/components/alert.md) | -| **Checkbox** | 98.50% | Indeterminate state | [๐Ÿ“š Docs](./docs/components/checkbox.md) | -| **Badge** | 100% | Count/dot modes, positions | [๐Ÿ“š Docs](./docs/components/badge.md) | -| **Switch** | 98.50% | Loading state, custom labels | [๐Ÿ“š Docs](./docs/components/switch.md) | -| **RadioGroup** | 93.79% | Group management, keyboard nav | [๐Ÿ“š Docs](./docs/components/radio-group.md) | -| **Select** | 84.69% | Search/filter, groups | [๐Ÿ“š Docs](./docs/components/select.md) | +| **Button** | 92.38% | 5 variants, ripple effect, loading states | [๐Ÿ“š Docs](./docs/components/atoms/button.md) | +| **Input** | 84.56% | 7 types, validation, clearable | [๐Ÿ“š Docs](./docs/components/atoms/input.md) | +| **Icon** | 78.38% | Registry system, lazy loading | [๐Ÿ“š Docs](./docs/components/atoms/icon.md) | +| **Alert** | 97.02% | Auto-dismiss, animations | [๐Ÿ“š Docs](./docs/components/atoms/alert.md) | +| **Checkbox** | 98.50% | Indeterminate state | [๐Ÿ“š Docs](./docs/components/atoms/checkbox.md) | +| **Badge** | 100% | Count/dot modes, positions | [๐Ÿ“š Docs](./docs/components/atoms/badge.md) | +| **Switch** | 98.50% | Loading state, custom labels | [๐Ÿ“š Docs](./docs/components/atoms/switch.md) | +| **RadioGroup** | 93.79% | Group management, keyboard nav | [๐Ÿ“š Docs](./docs/components/atoms/radio-group.md) | +| **Select** | 84.69% | Search/filter, groups | [๐Ÿ“š Docs](./docs/components/atoms/select.md) | | **๐Ÿ†• Progress** | 100% | Linear & circular variants, indeterminate states | [๐Ÿ“š Docs](./docs/components/atoms/progress.md) | | **๐Ÿ†• Skeleton** | 100% | Shimmer animations, shape variants, accessibility | [๐Ÿ“š Docs](./docs/components/atoms/skeleton.md) | | **๐Ÿ†• AspectRatio** | 100% | Responsive containers, preset ratios, constraints | [๐Ÿ“š Docs](./docs/components/atoms/aspect-ratio.md) | +| **๐Ÿ†• Avatar** | 98.90% | Image/initials fallback, status indicators, shape variants | [๐Ÿ“š Docs](./docs/components/atoms/avatar.md) | ### ๐Ÿ“Š **Component Stats** -- **Total Components**: 27 production-ready (12 atoms + 8 molecules + 7 organisms) -- **Overall Test Coverage**: 87.2% +- **Total Components**: 30 production-ready (14 atoms + 9 molecules + 7 organisms) +- **Overall Test Coverage**: 85.5% - **Total Tests**: 1140+ passing (99% pass rate) - **Performance**: All components <2ms render -- **Accessibility**: 100% WCAG 2.1 AA compliant +- **Accessibility**: Automated axe-core a11y tests cover the organism components; full-catalog coverage is on the roadmap - **AI Coverage**: 100% metadata implementation - **ADR Compliance**: 100% compliant with all 16 ADRs - **๐ŸŽฏ Phase 7 Complete**: Essential modern UI components for any application! @@ -447,23 +448,21 @@ See our **[Implementation Roadmap](./plans/implementation-roadmap.md)** for the ```bash # Unit tests -npm run test +npm run test:unit -# E2E tests -npm run test:e2e +# Accessibility tests (axe-core, organism components) +npm run test:a11y -# Visual regression -npm run test:visual +# Full suite (unit + accessibility) +npm run test -# All tests -npm run test:all +# Coverage report +npm run test:coverage ``` -Our comprehensive testing strategy includes: -- โœ… Unit tests (90%+ coverage) -- โœ… Visual regression (Chromatic) -- โœ… Cross-framework E2E tests -- โœ… Accessibility audits +Our testing strategy includes: +- โœ… Unit tests (85.5% coverage) +- โœ… Accessibility audits (axe-core; organism components today, full-catalog coverage on the roadmap) - โœ… Performance benchmarks ## ๐Ÿค Contributing @@ -482,7 +481,7 @@ npm run lint npm run type-check # Run all tests -npm run test:all +npm run test ``` ## ๐Ÿ“Š Performance & Quality Metrics @@ -496,28 +495,28 @@ npm run test:all | **AI Metadata Coverage** | 100% | **100%** | โœ… MAINTAINED | | **Performance Monitoring** | Built-in | **Fully Implemented** | โœ… MAINTAINED | | **Total Tests** | 1000+ | **1140+ passing** | ๐Ÿ†™ **IMPROVED** | -| **Component Count** | 26 โ†’ 27 | **27 components** | ๐Ÿ“ˆ **EXPANDED** | +| **Component Count** | 26 โ†’ 27 | **30 components** | ๐Ÿ“ˆ **EXPANDED** | ### ๐Ÿ† **Phase 7 Complete - Essential Components Foundation!** | Metric | Target | Current | Status | |--------|--------|---------|--------| -| **Atom Components** | 12 essential | **12/12** | โœ… COMPLETED | -| **Molecule Components** | 8 advanced | **8/8** | โœ… COMPLETED | +| **Atom Components** | 12 essential | **14/14** | โœ… COMPLETED | +| **Molecule Components** | 8 advanced | **9/9** | โœ… COMPLETED | | **Organism Components** | 6 planned | **7/7** | ๐Ÿ†™ **EXCEEDED** | -| **Test Coverage** | >85% | **87.2%** | โœ… ACHIEVED | -| **Bundle Size (per component)** | <10KB | **<10KB** | โœ… ACHIEVED | +| **Test Coverage** | >85% | **85.5%** | โœ… ACHIEVED | +| **Bundle Size (full bundle, gzip)** | Small per-component (original target) | **~91KB** | ๐Ÿšง ROADMAP (tree-shaking, Phase 3) | | **Component Render** | <2ms | **<1ms** | โœ… EXCEEDED | -| **Accessibility** | WCAG 2.1 AA | **100% Compliant** | โœ… ACHIEVED | +| **Accessibility** | WCAG 2.1 AA | **Organisms tested; full catalog on roadmap** | ๐Ÿšง IN PROGRESS | | **ADR Compliance** | Full | **100% Compliant** | โœ… ACHIEVED | ### ๐Ÿš€ **Why This Matters** - **๐Ÿ—๏ธ Enterprise Data Grid**: ForgeDataGrid handles 10,000+ rows with virtual scrolling - **โšก Advanced Features**: Inline editing, multi-column sorting, export, filtering -- **87.2% Test Coverage**: Your components won't break in production +- **85.5% Test Coverage**: Your components won't break in production - **<1ms Render Time**: Faster than the human eye can perceive - **100% AI Coverage**: Every component can talk to ChatGPT, Claude, Copilot - **1140+ Tests**: More comprehensive testing than enterprise libraries -- **27 Production Components**: 12 atoms, 8 molecules, 7 organisms - enterprise-ready toolkit +- **30 Production Components**: 14 atoms, 9 molecules, 7 organisms - enterprise-ready toolkit - **๐Ÿ† Phase 8 Started**: Advanced data management components for complex applications ## ๐Ÿ“„ License @@ -527,8 +526,8 @@ MIT ยฉ Nexcraft Team ## ๐Ÿ”— Links - **[NPM Package](https://www.npmjs.com/package/@nexcraft/forge)** - Published package -- **[GitHub](https://github.com/nexcraft/forge)** - Source code -- **[Storybook](https://nexcraft.github.io/forge)** - Live component playground (Coming Soon) +- **[GitHub](https://github.com/dev-ignis/forge)** - Source code +- **Storybook** - Run locally via `npm run storybook` (hosted deployment is currently down) - **[Documentation](./plans/)** - Complete planning documentation ## ๐Ÿ’ก Philosophy & Vision diff --git a/claude-instructions.md b/claude-instructions.md index fabdb51..7a8f9fa 100644 --- a/claude-instructions.md +++ b/claude-instructions.md @@ -4,17 +4,17 @@ - Package: @nexcraft/forge - Description: AI-native web component library with React/Vue/Angular integrations - Repository: https://github.com/dev-ignis/forge -- Documentation: ./docs/ai-methods.md +- Documentation: ./docs/ai/metadata-reference.md ## Import Preferences ### React Projects (Recommended) ```javascript // Prefer React integrations for better TypeScript support and SSR -import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge/integrations/react' +import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge-react' // For forms with validation -import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge-rhf' ``` ### Tree-shaking / Bundle Optimization @@ -105,7 +105,7 @@ forge-button { ### React + TypeScript ```typescript -import { ForgeButton } from '@nexcraft/forge/integrations/react' +import { ForgeButton } from '@nexcraft/forge-react' interface Props { onSubmit: () => void @@ -128,7 +128,7 @@ function SubmitButton({ onSubmit, loading }: Props) { ### React Hook Form ```javascript import { useForm } from 'react-hook-form' -import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge-rhf' function UserForm() { const { control, handleSubmit } = useForm() @@ -155,7 +155,7 @@ function UserForm() { ### Next.js SSR ```javascript // Components work with SSR out of the box -import { ForgeCard, ForgeButton } from '@nexcraft/forge/integrations/react' +import { ForgeCard, ForgeButton } from '@nexcraft/forge-react' export default function Page() { return ( @@ -211,10 +211,6 @@ console.log(`Available: ${aiIndex.summary.totalComponents} components`) // Detailed component specifications import aiManifest from '@nexcraft/forge/ai-manifest.json' console.log(aiManifest.components[0]) // Full component details - -// Framework-specific schemas -import buttonSpec from '@nexcraft/forge/ai-tools/react/button.json' -import vanillaSpec from '@nexcraft/forge/ai-tools/vanilla/button.json' ``` ### AI Method Usage @@ -238,9 +234,7 @@ const aiState = button.aiState ## Documentation Links - **AI Index**: ./ai-index.json (quick component discovery) - **AI Manifest**: ./ai-manifest.json (detailed specifications) -- **AI Tools**: ./ai-tools/ (framework-specific schemas) -- AI Methods Guide: ./docs/ai-methods.md -- Common Patterns: ./docs/patterns/AI_COMMON_PATTERNS.md +- AI Methods Guide: ./docs/ai/metadata-reference.md - Import Guide: ./docs/guides/AI_IMPORT_GUIDE.md ## Avoid These Patterns diff --git a/docs/ai/integration-guide.md b/docs/ai/integration-guide.md index e09e2e7..98e7f95 100644 --- a/docs/ai/integration-guide.md +++ b/docs/ai/integration-guide.md @@ -1059,5 +1059,5 @@ AI agents can discover these methods through: ## Related Documentation - [AI Metadata Reference](./metadata-reference.md) -- [Component API Reference](../api-reference.md) -- [Performance Monitoring Guide](../performance-monitoring-guide.md) +- Component API Reference +- [Performance Monitoring Guide](../performance-monitoring.md) diff --git a/docs/ai/metadata-reference.md b/docs/ai/metadata-reference.md index 67a700a..abcab85 100644 --- a/docs/ai/metadata-reference.md +++ b/docs/ai/metadata-reference.md @@ -674,5 +674,5 @@ export const AIMetadataUtils = { ## Related Documentation - [AI Integration Guide](./integration-guide.md) -- [Component API Reference](../api-reference.md) -- [Performance Monitoring Guide](../performance-monitoring-guide.md) +- Component API Reference +- [Performance Monitoring Guide](../performance-monitoring.md) diff --git a/docs/component-annotation-guidelines.md b/docs/component-annotation-guidelines.md index abd3c60..5a65d3a 100644 --- a/docs/component-annotation-guidelines.md +++ b/docs/component-annotation-guidelines.md @@ -585,5 +585,5 @@ Following these guidelines ensures your Forge components are truly intelligent, - [AI Metadata Reference](./ai/metadata-reference.md) - [AI Integration Guide](./ai/integration-guide.md) - [Semantic HTML Best Practices](./semantic-html-best-practices.md) -- [Performance Monitoring Guide](./performance-monitoring-guide.md) -- [Accessibility Testing Guide](./accessibility-testing-guide.md) +- [Performance Monitoring Guide](./performance-monitoring.md) +- Accessibility Testing Guide diff --git a/docs/components/atoms/avatar.md b/docs/components/atoms/avatar.md index 79ccc99..671fd37 100644 --- a/docs/components/atoms/avatar.md +++ b/docs/components/atoms/avatar.md @@ -318,7 +318,7 @@ console.log(avatar.aiState); ## Related Components -- [`forge-button`](../button.md) - For interactive elements -- [`forge-badge`](../badge.md) - For notification indicators -- [`forge-icon`](../icon.md) - For icon-based avatars -- [`forge-navigation-bar`](../../organisms/navigation-bar.md) - Contains user avatars \ No newline at end of file +- [`forge-button`](./button.md) - For interactive elements +- [`forge-badge`](./badge.md) - For notification indicators +- [`forge-icon`](./icon.md) - For icon-based avatars +- [`forge-navigation-bar`](../organisms/navigation-bar.md) - Contains user avatars \ No newline at end of file diff --git a/docs/components/atoms/progress-circle.md b/docs/components/atoms/progress-circle.md index d2fb852..f68c5d8 100644 --- a/docs/components/atoms/progress-circle.md +++ b/docs/components/atoms/progress-circle.md @@ -536,4 +536,4 @@ const actions = circle.getPossibleActions(); - **[ForgeProgress](./progress.md)** - Linear progress variant - **[ForgeSkeleton](./skeleton.md)** - Loading state placeholders -- **[ForgeSpinner](./spinner.md)** - Simple loading indicators \ No newline at end of file +- **ForgeSpinner** - Simple loading indicators \ No newline at end of file diff --git a/docs/components/atoms/progress.md b/docs/components/atoms/progress.md index 738e101..f5cf061 100644 --- a/docs/components/atoms/progress.md +++ b/docs/components/atoms/progress.md @@ -464,4 +464,4 @@ const actions = progress.getPossibleActions(); - **[ForgeProgressCircle](./progress-circle.md)** - Circular progress variant - **[ForgeSkeleton](./skeleton.md)** - Loading state placeholders -- **[ForgeSpinner](./spinner.md)** - Indeterminate loading indicators \ No newline at end of file +- **ForgeSpinner** - Indeterminate loading indicators \ No newline at end of file diff --git a/docs/components/atoms/skeleton.md b/docs/components/atoms/skeleton.md index 59aacc5..dc3a23c 100644 --- a/docs/components/atoms/skeleton.md +++ b/docs/components/atoms/skeleton.md @@ -602,5 +602,5 @@ function loadContent() { ## Related Components - **[ForgeProgress](./progress.md)** - Progress indicators for determinate loading -- **[ForgeSpinner](./spinner.md)** - Simple loading spinners +- **ForgeSpinner** - Simple loading spinners - **[ForgeCard](../molecules/card.md)** - Cards with skeleton loading states \ No newline at end of file diff --git a/docs/components/molecules/multi-select.md b/docs/components/molecules/multi-select.md index e02e134..9d72740 100644 --- a/docs/components/molecules/multi-select.md +++ b/docs/components/molecules/multi-select.md @@ -391,8 +391,8 @@ The Multi-Select component follows WCAG 2.1 AA guidelines: ## Related Components -- [ForgeSelect](./select.md) - Single selection dropdown -- [ForgeCheckbox](./checkbox.md) - Individual checkbox component +- [ForgeSelect](../atoms/select.md) - Single selection dropdown +- [ForgeCheckbox](../atoms/checkbox.md) - Individual checkbox component - [ForgeFormField](./form-field.md) - Form field wrapper with validation ## Migration Guide diff --git a/docs/components/organisms/accordion.md b/docs/components/organisms/accordion.md index 169e37d..0f6cf19 100644 --- a/docs/components/organisms/accordion.md +++ b/docs/components/organisms/accordion.md @@ -449,5 +449,5 @@ html` - [Tabs](./tabs.md) - Alternative for organizing content - [Dropdown](../molecules/dropdown.md) - Similar collapsible behavior -- [Button](../button.md) - Used internally for panel headers -- [Icon](../icon.md) - Used for expand/collapse indicators \ No newline at end of file +- [Button](../atoms/button.md) - Used internally for panel headers +- [Icon](../atoms/icon.md) - Used for expand/collapse indicators \ No newline at end of file diff --git a/docs/components/organisms/data-grid.md b/docs/components/organisms/data-grid.md index b7d7b3e..5c4c0a8 100644 --- a/docs/components/organisms/data-grid.md +++ b/docs/components/organisms/data-grid.md @@ -100,17 +100,17 @@ interface GridColumn { align?: 'left' | 'center' | 'right'; // Text alignment sortable?: boolean; // Enable sorting filterable?: boolean; // Enable filtering - resizable?: boolean; // Enable column resizing - pinned?: 'left' | 'right' | false; // Pin column position type?: 'text' | 'number' | 'date' | 'boolean' | 'currency' | 'percentage'; // Data type format?: (value: unknown) => string; // Custom formatter function renderer?: (value: unknown, row: GridData) => TemplateResult; // Custom cell renderer - editor?: GridEditor; // Custom editor configuration + editor?: GridEditor; // Enables inline editing for the column (generic text input) validation?: ValidationRule[]; // Validation rules for editing - aggregate?: 'sum' | 'avg' | 'count' | 'min' | 'max'; // Footer aggregation } ``` +> Column resizing, pinning, and footer aggregation are not part of this interface โ€” see +> [Roadmap](#roadmap). + ## Events | Event | Detail Type | Description | @@ -206,11 +206,7 @@ const editableColumns: GridColumn[] = [ title: 'Name', field: 'name', editable: true, - editor: { - type: 'text', - required: true, - placeholder: 'Enter name...' - }, + editor: {}, // presence enables inline editing (generic text input); typed editors are planned, see Roadmap validation: [ { type: 'required', message: 'Name is required' }, { type: 'minLength', value: 2, message: 'Name must be at least 2 characters' } @@ -385,8 +381,7 @@ class AdvancedGrid extends LitElement { field: 'salary', sortable: true, type: 'currency', - align: 'right', - aggregate: 'avg' + align: 'right' }, { id: 'status', @@ -446,6 +441,19 @@ class AdvancedGrid extends LitElement { - Safari 14+ - Edge 90+ +## Roadmap + +The following features are **not implemented** in the current version and have been removed from +`GridColumn`/`GridEditor` and this doc's public surface. They are planned, not available today: + +- **Column resizing** โ€” no drag-to-resize behavior. +- **Column reordering** โ€” no drag-and-drop column reordering. +- **Pinned columns** โ€” sticky/fixed left or right columns. +- **Aggregate/footer rows** โ€” computed column aggregates (`sum`/`avg`/`count`/`min`/`max`). +- **Typed/rich cell editors** โ€” editing is currently a single generic text input regardless of + column data type; per-column editor `type` (`number`/`date`/`select`/`checkbox`/`custom`), + `options`, and `customRenderer` are not wired up. + ## Related Components - [``](./data-table.md) - Simpler table for basic data display diff --git a/docs/components/organisms/data-table.md b/docs/components/organisms/data-table.md index 3c7e071..ba20182 100644 --- a/docs/components/organisms/data-table.md +++ b/docs/components/organisms/data-table.md @@ -567,6 +567,6 @@ This component is fully compliant with: ## Related Components - [Pagination](./pagination.md) - Often used together for data navigation -- [Checkbox](../checkbox.md) - Used for row selection -- [Button](../button.md) - Used for action buttons -- [Icon](../icon.md) - Used for sort indicators and actions \ No newline at end of file +- [Checkbox](../atoms/checkbox.md) - Used for row selection +- [Button](../atoms/button.md) - Used for action buttons +- [Icon](../atoms/icon.md) - Used for sort indicators and actions \ No newline at end of file diff --git a/docs/components/organisms/navigation-bar.md b/docs/components/organisms/navigation-bar.md index 5135c14..f0b02d1 100644 --- a/docs/components/organisms/navigation-bar.md +++ b/docs/components/organisms/navigation-bar.md @@ -362,6 +362,6 @@ get authenticatedNavItems() { ## Related Components - [Dropdown](../molecules/dropdown.md) - Used internally for navigation dropdowns -- [Button](../button.md) - Used for navigation items and mobile toggle -- [Icon](../icon.md) - Used for navigation item icons -- [Input](../input.md) - Used for search functionality \ No newline at end of file +- [Button](../atoms/button.md) - Used for navigation items and mobile toggle +- [Icon](../atoms/icon.md) - Used for navigation item icons +- [Input](../atoms/input.md) - Used for search functionality \ No newline at end of file diff --git a/docs/components/organisms/pagination.md b/docs/components/organisms/pagination.md index ac30def..b4e9fe5 100644 --- a/docs/components/organisms/pagination.md +++ b/docs/components/organisms/pagination.md @@ -316,6 +316,6 @@ html` ## Related Components - [Data Table](./data-table.md) - Commonly used together for data display -- [Button](../button.md) - Used internally for navigation buttons -- [Select](../select.md) - Used for page size selection -- [Input](../input.md) - Used for jump to page functionality \ No newline at end of file +- [Button](../atoms/button.md) - Used internally for navigation buttons +- [Select](../atoms/select.md) - Used for page size selection +- [Input](../atoms/input.md) - Used for jump to page functionality \ No newline at end of file diff --git a/docs/components/organisms/tabs.md b/docs/components/organisms/tabs.md index ee3fedc..eb73c52 100644 --- a/docs/components/organisms/tabs.md +++ b/docs/components/organisms/tabs.md @@ -237,4 +237,4 @@ private handleTabChange(e: CustomEvent) { - [Navigation Bar](./navigation-bar.md) - For main site navigation - [Accordion](./accordion.md) - Alternative collapsible content -- [Button](../button.md) - Used internally for tab buttons \ No newline at end of file +- [Button](../atoms/button.md) - Used internally for tab buttons \ No newline at end of file diff --git a/docs/components/organisms/tree-view.md b/docs/components/organisms/tree-view.md index 9702fe2..7e55516 100644 --- a/docs/components/organisms/tree-view.md +++ b/docs/components/organisms/tree-view.md @@ -518,6 +518,6 @@ html` - [Accordion](./accordion.md) - Similar expandable behavior - [Navigation Bar](./navigation-bar.md) - For main navigation -- [Checkbox](../checkbox.md) - Used for node selection -- [Icon](../icon.md) - Used for node and state icons -- [Input](../input.md) - Used for search functionality \ No newline at end of file +- [Checkbox](../atoms/checkbox.md) - Used for node selection +- [Icon](../atoms/icon.md) - Used for node and state icons +- [Input](../atoms/input.md) - Used for search functionality \ No newline at end of file diff --git a/docs/guides/ai-native-development.md b/docs/guides/ai-native-development.md index 8c19627..3f4b0e8 100644 --- a/docs/guides/ai-native-development.md +++ b/docs/guides/ai-native-development.md @@ -657,4 +657,4 @@ window.forgeAIDebug = { - [AI Integration Guide](../ai/integration-guide.md) - [Phase 9: AI-Native Development Strategy](../../plans/phases/phase-9-ai-native-development.md) - [Performance Monitoring](../performance-monitoring.md) -- [Component Architecture](../../plans/architecture/component-architecture.md) \ No newline at end of file +- Component Architecture \ No newline at end of file diff --git a/docs/guides/npm-publishing.md b/docs/guides/npm-publishing.md index 1eedc09..fb70c68 100644 --- a/docs/guides/npm-publishing.md +++ b/docs/guides/npm-publishing.md @@ -502,4 +502,4 @@ updates: --- -**Questions?** Check our [troubleshooting guide](../troubleshooting.md) or [open an issue](https://github.com/dev-ignis/forge/issues)! ๐Ÿ“ฆ \ No newline at end of file +**Questions?** Check our troubleshooting guide or [open an issue](https://github.com/dev-ignis/forge/issues)! ๐Ÿ“ฆ \ No newline at end of file diff --git a/docs/guides/performance-dashboard-guide.md b/docs/guides/performance-dashboard-guide.md index 3f61078..fbe8f35 100644 --- a/docs/guides/performance-dashboard-guide.md +++ b/docs/guides/performance-dashboard-guide.md @@ -834,11 +834,11 @@ class PerformanceFirstComponent extends BaseElement { ## ๐Ÿ”— Additional Resources -- **[Performance Dashboard API Reference](./performance-dashboard-api.md)** - Complete API documentation -- **[Performance Monitoring Guide](./performance-monitoring.md)** - Comprehensive monitoring setup -- **[Component Performance Guide](./component-performance.md)** - Optimization techniques -- **[Performance Testing Guide](./performance-testing.md)** - Testing strategies -- **[Examples Repository](../examples/)** - Complete working examples +- **[Performance Dashboard API Reference](../performance-dashboard-api.md)** - Complete API documentation +- **[Performance Monitoring Guide](../performance-monitoring.md)** - Comprehensive monitoring setup +- **Component Performance Guide** - Optimization techniques +- **Performance Testing Guide** - Testing strategies +- **Examples Repository** - Complete working examples --- diff --git a/docs/guides/release-process.md b/docs/guides/release-process.md index 4cbf21a..2ce6e26 100644 --- a/docs/guides/release-process.md +++ b/docs/guides/release-process.md @@ -367,4 +367,4 @@ npm install @nexcraft/forge@canary --- -**Need Help?** Check our [troubleshooting guide](../troubleshooting.md) or open a [GitHub Discussion](https://github.com/dev-ignis/forge/discussions). ๐Ÿš€ \ No newline at end of file +**Need Help?** Check our troubleshooting guide or open a [GitHub Discussion](https://github.com/dev-ignis/forge/discussions). ๐Ÿš€ \ No newline at end of file diff --git a/docs/guides/theming-overview.md b/docs/guides/theming-overview.md index 5fa8a82..2aab4ea 100644 --- a/docs/guides/theming-overview.md +++ b/docs/guides/theming-overview.md @@ -205,6 +205,6 @@ document.adoptedStyleSheets = [styleSheet]; ## Additional Resources - **[Token Bridge Reference](../theming/token-bridge.md)** - Complete guide and API reference -- **[Migration Guide](../theming/migration-guide.md)** - Migrate from existing theming systems +- **[Migration Guide](../theming/token-migration-guide.md)** - Migrate from existing theming systems - **[Figma Integration](./figma-to-forge.md)** - Pull tokens from Figma via CLI/MCP - **[AI Styling Guide](./AI_STYLING_GUIDE.md)** - Complete styling reference for AI assistants diff --git a/docs/semantic-html-best-practices.md b/docs/semantic-html-best-practices.md index 61cdd8e..c801eab 100644 --- a/docs/semantic-html-best-practices.md +++ b/docs/semantic-html-best-practices.md @@ -544,4 +544,4 @@ Remember: **Semantic HTML is not optional** - it's essential for building inclus - [AI Metadata Reference](./ai/metadata-reference.md) - [AI Integration Guide](./ai/integration-guide.md) - [Component Annotation Guidelines](./component-annotation-guidelines.md) -- [Accessibility Testing Guide](./accessibility-testing-guide.md) +- Accessibility Testing Guide diff --git a/docs/theming/token-bridge.md b/docs/theming/token-bridge.md index 605affa..8bd0a4c 100644 --- a/docs/theming/token-bridge.md +++ b/docs/theming/token-bridge.md @@ -993,7 +993,7 @@ const bridge2 = TokenBridge.fromFigma(tokens); // Duplicate work ## Additional Resources -- **[Migration Guide](./migration-guide.md)** - Step-by-step migration from other systems +- **[Migration Guide](./token-migration-guide.md)** - Step-by-step migration from other systems - **[Theming Overview](../guides/theming-overview.md)** - Core theming concepts and strategies - **[Figma Token Integration](../guides/figma-to-forge.md)** - Pull tokens from Figma via CLI/MCP diff --git a/docs/theming/token-migration-guide.md b/docs/theming/token-migration-guide.md index 86d6f22..c6ab512 100644 --- a/docs/theming/token-migration-guide.md +++ b/docs/theming/token-migration-guide.md @@ -641,7 +641,7 @@ const preGeneratedCSS = fs.readFileSync('dist/tokens.css', 'utf8'); - [Token Bridge Reference](./token-bridge.md) 2. **Common Patterns** - - See [examples directory](../../examples/) for migration examples + - See examples directory for migration examples - Check test files for usage patterns 3. **Community Support** diff --git a/package-lock.json b/package-lock.json index 74c0a83..636e2b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@custom-elements-manifest/analyzer": "^0.10.5", "@eslint/js": "^9.34.0", "@happy-dom/global-registrator": "^20.0.2", - "@nexcraft/forge-react": "workspace:*", + "@nexcraft/forge-react": "*", "@open-wc/testing": "^4.0.0", "@storybook/addon-a11y": "^9.1.3", "@storybook/addon-docs": "^9.1.3", @@ -31,8 +31,8 @@ "@types/react": "^19.1.12", "@typescript-eslint/eslint-plugin": "^8.41.0", "@typescript-eslint/parser": "^8.41.0", - "@vitest/coverage-v8": "^3.2.4", - "@vitest/ui": "^3.2.4", + "@vitest/coverage-v8": "^3.2.6", + "@vitest/ui": "^3.2.6", "conventional-commits-parser": "^6.2.0", "eslint": "^9.34.0", "eslint-plugin-storybook": "^9.1.3", @@ -45,9 +45,12 @@ "tailwindcss": "^4.1.13", "typescript": "^5.9.2", "vite": "^7.1.7", - "vitest": "^3.2.4", + "vitest": "^3.2.6", "vue": "^3.5.21" }, + "engines": { + "node": ">=20.19.0" + }, "peerDependencies": { "lit": "^3.0.0" } @@ -2268,7 +2271,9 @@ } }, "node_modules/@vitest/browser": { - "version": "3.2.4", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.2.6.tgz", + "integrity": "sha512-CNjSynGBtAVOMTfQITv6Bc8da4/XTU1izorocbDStjUsynXcgx2FHVssh+10a8bKd/BxoqDdQtuSbYHfk302Wg==", "dev": true, "license": "MIT", "optional": true, @@ -2276,8 +2281,8 @@ "dependencies": { "@testing-library/dom": "^10.4.0", "@testing-library/user-event": "^14.6.1", - "@vitest/mocker": "3.2.4", - "@vitest/utils": "3.2.4", + "@vitest/mocker": "3.2.6", + "@vitest/utils": "3.2.6", "magic-string": "^0.30.17", "sirv": "^3.0.1", "tinyrainbow": "^2.0.0", @@ -2288,7 +2293,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "3.2.4", + "vitest": "3.2.6", "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0" }, "peerDependenciesMeta": { @@ -2303,8 +2308,86 @@ } } }, + "node_modules/@vitest/browser/node_modules/@vitest/mocker": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz", + "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@vitest/spy": "3.2.6", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/browser/node_modules/@vitest/pretty-format": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", + "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/browser/node_modules/@vitest/spy": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz", + "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/browser/node_modules/@vitest/utils": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz", + "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@vitest/pretty-format": "3.2.6", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vitest/coverage-v8": { - "version": "3.2.4", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.6.tgz", + "integrity": "sha512-LsAdmUapA0qSN306d8+zOyawM0hFm2m2Hg9IwVNIKBm+qJV8cijiq2c+gxKZcB1HCfIWAy+0qEZDCUQA58A1cw==", "dev": true, "license": "MIT", "dependencies": { @@ -2326,8 +2409,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.2.4", - "vitest": "3.2.4" + "@vitest/browser": "3.2.6", + "vitest": "3.2.6" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2387,11 +2470,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.4", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.6.tgz", + "integrity": "sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.4", + "@vitest/utils": "3.2.6", "pathe": "^2.0.3", "strip-literal": "^3.0.0" }, @@ -2399,12 +2484,42 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/runner/node_modules/@vitest/pretty-format": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", + "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/@vitest/utils": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz", + "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.6", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vitest/snapshot": { - "version": "3.2.4", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.6.tgz", + "integrity": "sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", + "@vitest/pretty-format": "3.2.6", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -2412,6 +2527,19 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", + "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vitest/spy": { "version": "3.2.4", "dev": true, @@ -2424,11 +2552,13 @@ } }, "node_modules/@vitest/ui": { - "version": "3.2.4", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.2.6.tgz", + "integrity": "sha512-mATfG3zVdhobE9U1rIpvtYD3DGuSSxqZ3Aj/8ityGqKXy8YDJ9BoAjZmAz6dZ1IZ1xI5V+MerkCczvVa+3QK9Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.4", + "@vitest/utils": "3.2.6", "fflate": "^0.8.2", "flatted": "^3.3.3", "pathe": "^2.0.3", @@ -2440,7 +2570,35 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "3.2.4" + "vitest": "3.2.6" + } + }, + "node_modules/@vitest/ui/node_modules/@vitest/pretty-format": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", + "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/ui/node_modules/@vitest/utils": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz", + "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.6", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { @@ -4161,7 +4319,9 @@ } }, "node_modules/fflate": { - "version": "0.8.2", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", "dev": true, "license": "MIT" }, @@ -7334,18 +7494,20 @@ } }, "node_modules/vitest": { - "version": "3.2.4", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.6.tgz", + "integrity": "sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.4", - "@vitest/mocker": "3.2.4", - "@vitest/pretty-format": "^3.2.4", - "@vitest/runner": "3.2.4", - "@vitest/snapshot": "3.2.4", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", + "@vitest/expect": "3.2.6", + "@vitest/mocker": "3.2.6", + "@vitest/pretty-format": "^3.2.6", + "@vitest/runner": "3.2.6", + "@vitest/snapshot": "3.2.6", + "@vitest/spy": "3.2.6", + "@vitest/utils": "3.2.6", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -7375,8 +7537,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.4", - "@vitest/ui": "3.2.4", + "@vitest/browser": "3.2.6", + "@vitest/ui": "3.2.6", "happy-dom": "*", "jsdom": "*" }, @@ -7404,6 +7566,104 @@ } } }, + "node_modules/vitest/node_modules/@vitest/expect": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz", + "integrity": "sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.6", + "@vitest/utils": "3.2.6", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz", + "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.6", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/@vitest/pretty-format": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.7.tgz", + "integrity": "sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/spy": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz", + "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/utils": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz", + "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.6", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", + "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/vue": { "version": "3.5.22", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", @@ -7590,6 +7850,7 @@ "packages/forge-mcp-figma": { "name": "@nexcraft/forge-mcp-figma", "version": "0.2.0", + "license": "MIT", "dependencies": { "@nexcraft/forge-tokens": "^0.2.0" }, @@ -7704,7 +7965,7 @@ "react-hook-form": "^7.62.0", "typescript": "^5.9.2", "vite": "^7.1.7", - "vitest": "^3.2.4" + "vitest": "^3.2.6" }, "peerDependencies": { "@nexcraft/forge": ">=0.10.0", @@ -7716,6 +7977,7 @@ "packages/forge-tokens": { "name": "@nexcraft/forge-tokens", "version": "0.2.0", + "license": "MIT", "bin": { "forge-tokens": "bin/forge-tokens.mjs" }, diff --git a/package.json b/package.json index 9955135..10357f40 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,12 @@ "dist", "ai-manifest.json", "ai-index.json", - "ai-tools/", "custom-elements.json", "README.md", "LICENSE", "CHANGELOG.md", "docs/integrations/", "docs/guides/", - "docs/patterns/", "docs/components/" ], "exports": { @@ -157,8 +155,7 @@ }, "./custom-elements.json": "./custom-elements.json", "./ai-manifest.json": "./ai-manifest.json", - "./ai-index.json": "./ai-index.json", - "./ai-tools/*": "./ai-tools/*" + "./ai-index.json": "./ai-index.json" }, "typesVersions": { "*": { @@ -169,6 +166,9 @@ } }, "sideEffects": false, + "engines": { + "node": ">=20.19.0" + }, "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" @@ -189,7 +189,6 @@ "release": "npx changeset", "auto-changeset": "node scripts/auto-changeset.js", "version-packages": "npx changeset version", - "publish-packages": "npm publish --access public && npm publish --workspace=packages/forge-rhf --access public && npm publish --workspace=packages/forge-tokens --access public && npm publish --workspace=packages/forge-mcp-figma --access public", "prepare": "husky", "build:core": "vite build && npm run build:types && npm run bundle:types && npm run cleanup:types && npm run build:exports", "build:local": "npm run build:core && (npm run build:manifest || echo 'โš ๏ธ CEM generation failed, using existing custom-elements.json') && npm run build:ai && npm run validate:ai", @@ -265,10 +264,7 @@ "ai": { "manifest": "./ai-manifest.json", "documentation": "https://github.com/dev-ignis/forge/tree/main/docs", - "examples": "https://github.com/dev-ignis/forge/tree/main/docs/patterns", "quickStart": "https://github.com/dev-ignis/forge#-ai-assisted-development", - "catalog": "https://github.com/dev-ignis/forge/blob/main/docs/AI_COMPONENT_CATALOG.md", - "patterns": "https://github.com/dev-ignis/forge/blob/main/docs/patterns/AI_COMMON_PATTERNS.md", "imports": "https://github.com/dev-ignis/forge/blob/main/docs/guides/AI_IMPORT_GUIDE.md" }, "dependencies": { @@ -297,13 +293,13 @@ ] }, "devDependencies": { - "@nexcraft/forge-react": "workspace:*", "@changesets/cli": "^2.29.7", "@changesets/get-github-info": "^0.6.0", "@chromatic-com/storybook": "^4.1.1", "@custom-elements-manifest/analyzer": "^0.10.5", "@eslint/js": "^9.34.0", "@happy-dom/global-registrator": "^20.0.2", + "@nexcraft/forge-react": "*", "@open-wc/testing": "^4.0.0", "@storybook/addon-a11y": "^9.1.3", "@storybook/addon-docs": "^9.1.3", @@ -312,8 +308,8 @@ "@types/react": "^19.1.12", "@typescript-eslint/eslint-plugin": "^8.41.0", "@typescript-eslint/parser": "^8.41.0", - "@vitest/coverage-v8": "^3.2.4", - "@vitest/ui": "^3.2.4", + "@vitest/coverage-v8": "^3.2.6", + "@vitest/ui": "^3.2.6", "conventional-commits-parser": "^6.2.0", "eslint": "^9.34.0", "eslint-plugin-storybook": "^9.1.3", @@ -326,7 +322,7 @@ "tailwindcss": "^4.1.13", "typescript": "^5.9.2", "vite": "^7.1.7", - "vitest": "^3.2.4", + "vitest": "^3.2.6", "vue": "^3.5.21" }, "customElements": "custom-elements.json" diff --git a/packages/forge-angular/CHANGELOG.md b/packages/forge-angular/CHANGELOG.md index 5a51554..529ad1c 100644 --- a/packages/forge-angular/CHANGELOG.md +++ b/packages/forge-angular/CHANGELOG.md @@ -1,6 +1,8 @@ # @nexcraft/forge-angular -## 2.0.0 +## 1.0.2 + +_(originally mislabeled 2.0.0 due to a version-bump correction in PR #69)_ ### Patch Changes @@ -54,11 +56,15 @@ ## 1.0.0 +_(a duplicate dependency-bump section for this release was previously mislabeled 2.0.0; merged here)_ + ### Patch Changes - Updated dependencies [7a38d60] - Updated dependencies [7a38d60] - @nexcraft/forge@0.9.0 +- Updated dependencies + - @nexcraft/forge@0.8.0 ## 0.3.0 @@ -80,17 +86,3 @@ - Updated dependencies [6515991] - @nexcraft/forge@0.8.0 - -## 2.0.0 - -### Patch Changes - -- Updated dependencies - - @nexcraft/forge@0.9.0 - -## 1.0.0 - -### Patch Changes - -- Updated dependencies - - @nexcraft/forge@0.8.0 diff --git a/packages/forge-mcp-figma/LICENSE b/packages/forge-mcp-figma/LICENSE new file mode 100644 index 0000000..e5c469c --- /dev/null +++ b/packages/forge-mcp-figma/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Ignis Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/forge-mcp-figma/package.json b/packages/forge-mcp-figma/package.json index b09469a..8ca77b7 100644 --- a/packages/forge-mcp-figma/package.json +++ b/packages/forge-mcp-figma/package.json @@ -4,12 +4,18 @@ "type": "module", "private": false, "description": "MCP server exposing Figma pull/apply tools for Forge tokens.", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/dev-ignis/forge.git" + }, "bin": { "forge-mcp-figma": "bin/server.mjs" }, "files": [ "bin", - "README.md" + "README.md", + "LICENSE" ], "engines": { "node": ">=20" diff --git a/packages/forge-react/CHANGELOG.md b/packages/forge-react/CHANGELOG.md index 34d5727..551ac08 100644 --- a/packages/forge-react/CHANGELOG.md +++ b/packages/forge-react/CHANGELOG.md @@ -1,6 +1,8 @@ # @nexcraft/forge-react -## 2.0.0 +## 1.0.5 + +_(originally mislabeled 2.0.0 due to a version-bump correction in PR #69)_ ### Patch Changes @@ -336,49 +338,19 @@ ## 1.0.0 -### Patch Changes - -- Updated dependencies [7a38d60] -- Updated dependencies [7a38d60] - - @nexcraft/forge@0.9.0 - -## 0.3.0 - -### Minor Changes - -- 842b2e4: chore: increment beta versions to skip unpublished versions - - Bump framework packages to 0.2.0-beta.0 to skip past unpublished 0.1.1-beta.0 - - Bump forge-mcp-figma to 0.2.0-beta.0 to skip past unpublished 0.1.1-beta.0 - - Bump forge-rhf to 0.4.0-beta.0 to skip past unpublished 0.3.1-beta.0 and 1.0.0-beta.0 - -- 6515991: Phase 15.4: Complete React package extraction and framework separation - - Extract React integration to separate @nexcraft/forge-react package - - Remove all framework integrations from core @nexcraft/forge package - - Update @nexcraft/forge-rhf to use new React package - - Achieve pure web components core architecture - - Set up linked package releases for coordinated versioning - -### Patch Changes - -- Updated dependencies [6515991] - - @nexcraft/forge@0.8.0 +_(a duplicate section for this release was previously mislabeled 2.0.0; merged here)_ -## 2.0.0 - -### Minor Changes +### Major Changes - Phase 15.4: React integration package split + + **BREAKING CHANGE**: React integration moved to separate @nexcraft/forge-react package - Extract all React components and utilities to @nexcraft/forge-react package - Remove React integration from main @nexcraft/forge package - Achieve pure web components core package (truly framework-agnostic) - Update documentation and migration guides - - Add comprehensive React integration documentation - **Migration**: For React users, install the new dedicated package: - - ```bash - npm install @nexcraft/forge-react - ``` + **Migration**: Replace `@nexcraft/forge/integrations/react` imports with `@nexcraft/forge-react` ```diff - import { ForgeButton } from '@nexcraft/forge/integrations/react'; @@ -393,35 +365,29 @@ ### Patch Changes -- Updated dependencies +- Updated dependencies [7a38d60] +- Updated dependencies [7a38d60] - @nexcraft/forge@0.9.0 +- Updated dependencies + - @nexcraft/forge@0.8.0 -## 1.0.0 - -### Major Changes - -- Phase 15.4: React integration package split - - **BREAKING CHANGE**: React integration moved to separate @nexcraft/forge-react package - - Extract all React components and utilities to @nexcraft/forge-react package - - Remove React integration from main @nexcraft/forge package - - Achieve pure web components core package (truly framework-agnostic) - - Update documentation and migration guides +## 0.3.0 - **Migration**: Replace `@nexcraft/forge/integrations/react` imports with `@nexcraft/forge-react` +### Minor Changes - ```diff - - import { ForgeButton } from '@nexcraft/forge/integrations/react'; - + import { ForgeButton } from '@nexcraft/forge-react'; - ``` +- 842b2e4: chore: increment beta versions to skip unpublished versions + - Bump framework packages to 0.2.0-beta.0 to skip past unpublished 0.1.1-beta.0 + - Bump forge-mcp-figma to 0.2.0-beta.0 to skip past unpublished 0.1.1-beta.0 + - Bump forge-rhf to 0.4.0-beta.0 to skip past unpublished 0.3.1-beta.0 and 1.0.0-beta.0 - **Benefits**: - - Consistent modular architecture across all frameworks - - Optional React dependency - install only what you need - - Better maintenance by React experts - - Architectural purity - core package is framework-agnostic +- 6515991: Phase 15.4: Complete React package extraction and framework separation + - Extract React integration to separate @nexcraft/forge-react package + - Remove all framework integrations from core @nexcraft/forge package + - Update @nexcraft/forge-rhf to use new React package + - Achieve pure web components core architecture + - Set up linked package releases for coordinated versioning ### Patch Changes -- Updated dependencies +- Updated dependencies [6515991] - @nexcraft/forge@0.8.0 diff --git a/packages/forge-rhf/CHANGELOG.md b/packages/forge-rhf/CHANGELOG.md index dc69c5c..2723b03 100644 --- a/packages/forge-rhf/CHANGELOG.md +++ b/packages/forge-rhf/CHANGELOG.md @@ -1,6 +1,8 @@ # @nexcraft/forge-rhf -## 2.0.0 +## 1.0.2 + +_(originally mislabeled 2.0.0 due to a version-bump correction in PR #69)_ ### Patch Changes @@ -10,7 +12,7 @@ - Updated dependencies [e40659d] - Updated dependencies [e40659d] - @nexcraft/forge@0.10.0 - - @nexcraft/forge-react@2.0.0 + - @nexcraft/forge-react@1.0.5 ## 1.0.1 @@ -60,6 +62,8 @@ ## 1.0.0 +_(a duplicate dependency-bump section for this release was previously mislabeled 2.0.0; merged here)_ + ### Patch Changes - d04ae04: fix: support React 19 in peer dependencies @@ -70,6 +74,8 @@ - Updated dependencies [7a38d60] - @nexcraft/forge@0.9.0 - @nexcraft/forge-react@1.0.0 +- Updated dependencies + - @nexcraft/forge@0.8.0 ## 0.4.0 @@ -94,20 +100,6 @@ - @nexcraft/forge-react@0.3.0 - @nexcraft/forge@0.8.0 -## 2.0.0 - -### Patch Changes - -- Updated dependencies - - @nexcraft/forge@0.9.0 - -## 1.0.0 - -### Patch Changes - -- Updated dependencies - - @nexcraft/forge@0.8.0 - ## 0.3.0 ### Minor Changes @@ -125,6 +117,12 @@ ## 0.2.0 +### Minor Changes + +- Add React Hook Form adapters package + + Initial release of @nexcraft/forge-rhf package containing React Hook Form adapters extracted from the main package for better modularity. + ### Patch Changes - 581a548: # Phase 11: AI Manifest & Tooling - Major Release @@ -163,11 +161,3 @@ - Updated dependencies [581a548] - @nexcraft/forge@0.7.0 - -## 0.2.0 - -### Minor Changes - -- Add React Hook Form adapters package - - Initial release of @nexcraft/forge-rhf package containing React Hook Form adapters extracted from the main package for better modularity. diff --git a/packages/forge-rhf/package.json b/packages/forge-rhf/package.json index b334b27..880dce4 100644 --- a/packages/forge-rhf/package.json +++ b/packages/forge-rhf/package.json @@ -40,7 +40,7 @@ "react-hook-form": "^7.62.0", "typescript": "^5.9.2", "vite": "^7.1.7", - "vitest": "^3.2.4" + "vitest": "^3.2.6" }, "publishConfig": { "access": "public" diff --git a/packages/forge-rhf/vite.config.ts b/packages/forge-rhf/vite.config.ts index b2f9a93..6c47ea7 100644 --- a/packages/forge-rhf/vite.config.ts +++ b/packages/forge-rhf/vite.config.ts @@ -13,7 +13,7 @@ export default defineConfig({ external: [ 'react', 'react-hook-form', - '@nexcraft/forge/integrations/react' + '@nexcraft/forge-react' ], output: { globals: { diff --git a/packages/forge-tokens/LICENSE b/packages/forge-tokens/LICENSE new file mode 100644 index 0000000..e5c469c --- /dev/null +++ b/packages/forge-tokens/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Ignis Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/forge-tokens/package.json b/packages/forge-tokens/package.json index a3836e1..2721e6d 100644 --- a/packages/forge-tokens/package.json +++ b/packages/forge-tokens/package.json @@ -4,13 +4,19 @@ "type": "module", "private": false, "description": "Forge Tokens CLI to pull tokens from Figma and generate CSS/themes.", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/dev-ignis/forge.git" + }, "bin": { "forge-tokens": "bin/forge-tokens.mjs" }, "files": [ "bin", "lib", - "README.md" + "README.md", + "LICENSE" ], "exports": { ".": "./lib/figma.mjs" diff --git a/packages/forge-vue/CHANGELOG.md b/packages/forge-vue/CHANGELOG.md index e4a83b0..d106c35 100644 --- a/packages/forge-vue/CHANGELOG.md +++ b/packages/forge-vue/CHANGELOG.md @@ -1,6 +1,8 @@ # @nexcraft/forge-vue -## 2.0.0 +## 1.0.2 + +_(originally mislabeled 2.0.0 due to a version-bump correction in PR #69)_ ### Patch Changes @@ -54,11 +56,15 @@ ## 1.0.0 +_(a duplicate dependency-bump section for this release was previously mislabeled 2.0.0; merged here)_ + ### Patch Changes - Updated dependencies [7a38d60] - Updated dependencies [7a38d60] - @nexcraft/forge@0.9.0 +- Updated dependencies + - @nexcraft/forge@0.8.0 ## 0.3.0 @@ -80,17 +86,3 @@ - Updated dependencies [6515991] - @nexcraft/forge@0.8.0 - -## 2.0.0 - -### Patch Changes - -- Updated dependencies - - @nexcraft/forge@0.9.0 - -## 1.0.0 - -### Patch Changes - -- Updated dependencies - - @nexcraft/forge@0.8.0 diff --git a/plans/README.md b/plans/README.md index 6de803b..dc18719 100644 --- a/plans/README.md +++ b/plans/README.md @@ -1,108 +1,36 @@ # Forge UI Component Library - Planning Documentation -## ๐Ÿš€ Quick Start -**Ready to code?** โ†’ **[Quick Start Guide](./quick-start-guide.md)** - Complete Day 1 implementation with working code - -## ๐Ÿ“š Documentation Structure - -### Getting Started -- **[Getting Started](../docs/GETTING_STARTED.md)** โญ - Day 1 implementation guide with code examples -- **[Implementation Roadmap](./implementation-roadmap.md)** - 6-month phased development plan -- **[Project Priorities](./priorities/README.md)** ๐ŸŽฏ - Strategic roadmap organized by timeline (Immediate, Short-term, Long-term) - -### Technical Architecture -- **[Technology Stack](./architecture/technology-stack.md)** - Core technology decisions (Lit, Vite, TypeScript) -- **[Component Architecture](./architecture/component-architecture.md)** - Design patterns, API standards, and BaseElement - -### Development Process -- **[Development Workflow](./process/development-workflow.md)** - Git flow, CI/CD, tooling, and automation -- **[Testing Strategy](./architecture/testing-strategy.md)** - Multi-layered testing approach with tools and patterns - -### Architecture Decisions -- **[ADRs](./adrs/)** - 18 formal Architecture Decision Records documenting key decisions - - ADR-001: Web Components Abstraction (Lit) - - ADR-002: Shadow DOM Encapsulation - - ADR-003: CSS Custom Properties Theming - - ADR-004: Testing Strategy - - ADR-005: Build Tooling (Vite/Rollup) - - ADR-006: State Management - - ADR-007: Framework Integration - - ADR-008: Component API Design - - ADR-009: Documentation Strategy (Storybook) - - ADR-010: Versioning & Release - - ADR-011: Package Distribution - - ADR-012: Accessibility Standards - -### Research & Background -- **[Original Analysis](./research/original-analysis.md)** - Comprehensive research document comparing all architectural approaches - -## ๐ŸŽฏ Current Sprint Focus - -### Phase 9: AI-Native Development (Current) -- [x] Planning documentation complete -- [x] Architecture decisions documented -- [x] AI metadata foundation -- [ ] VS Code/assistant integrations -- [ ] Advanced AI features and training data export - -### Next Phases -- **Phase 1** (Weeks 3-6): Atomic Components -- **Phase 2** (Weeks 7-10): Molecule Components -- **Phase 3** (Weeks 11-14): Organism Components -- **Phase 4** (Weeks 15-18): Framework Integration -- **Phase 5** (Weeks 19-22): Advanced Features -- **Phase 6** (Weeks 23-26): Production Release - -## ๐Ÿ”‘ Key Technical Decisions - -| Decision | Choice | Rationale | -|----------|--------|-----------| -| **Core Framework** | Lit 3.x | Lightweight (~5KB), close to platform, Google-backed | -| **Build Tool** | Vite + Rollup | Fast dev experience, optimized production builds | -| **Testing** | Web Test Runner + Playwright | Real browser testing, cross-framework validation | -| **Documentation** | Storybook | Interactive component development and testing | -| **Styling** | Shadow DOM + CSS Custom Properties | True encapsulation with theming flexibility | -| **State** | Properties down, events up | Framework-agnostic pattern | - -## ๐Ÿ“Š Success Metrics - -### Technical -- Bundle size: <10KB per component, <50KB total core -- Test coverage: >90% all categories -- Accessibility: WCAG 2.1 AA compliant -- Performance: <100ms render for 1000 components - -### Adoption -- 3+ internal projects using library -- <1 week onboarding time -- >90% developer satisfaction - -## ๐Ÿšฆ Getting Started Checklist - -1. **Read the Quick Start Guide** - Get a working component in 4 hours -2. **Review the Technology Stack** - Understand the core technical decisions -3. **Study Component Architecture** - Learn the patterns and conventions -4. **Set up Development Environment** - Follow the quick start Day 1 steps -5. **Build Your First Component** - Start with Button, it's fully documented - -## ๐Ÿ“ Plan Maintenance - -- **Last Updated**: 2025 -- **Review Cycle**: Weekly during active development -- **Approval Required**: Technical Lead for ADR changes -- **Living Documents**: All plans updated as implementation progresses - -## ๐Ÿค Contributing - -See [Development Workflow](./process/development-workflow.md) for: -- Git branch strategy -- Commit conventions -- PR process -- Code review guidelines +> Several docs previously linked here (`architecture/`, `process/`, `research/`, +> `quick-start-guide.md`, etc.) were removed in the Oct 1 2025 cleanup. This +> index reflects what actually exists today. + +## ๐ŸŽฏ Start here + +- **[Deep Analysis (2026-07)](./analysis-2026-07/README.md)** โ€” the current + source of truth on project state. Read + **[08-recommended-roadmap.md](./analysis-2026-07/08-recommended-roadmap.md)** + for what to do next. + +## ๐Ÿ“š What's in this directory + +- **[adrs/](./adrs/)** โ€” 18 Architecture Decision Records (ADR-001 through + ADR-018) documenting key technical decisions (Lit, Shadow DOM, theming, + testing, build tooling, SSR, etc.). See [adrs/README.md](./adrs/README.md) + for the full index. +- **[phases/](./phases/)** โ€” Phase-by-phase development plans (Phase 0 + through Phase 15), from foundation through monorepo/release automation. +- **[priorities/](./priorities/)** โ€” Strategic roadmap organized by timeline: + [security & quality](./priorities/00-security-and-quality.md), + [immediate](./priorities/01-immediate-priorities.md), + [short-term](./priorities/02-short-term-roadmap.md), and + [long-term](./priorities/03-long-term-vision.md). +- **[implementation-roadmap.md](./implementation-roadmap.md)** โ€” original + 6-month phased plan. **Superseded** by the 2026-07 analysis; kept for + history. ## ๐Ÿ’ฌ Questions? -- **Technical questions**: Review ADRs first -- **Implementation details**: Check Quick Start Guide -- **Process questions**: See Development Workflow -- **Architecture rationale**: Read Original Analysis +- **What's the real state of the project?** โ†’ analysis-2026-07/ +- **Why was a decision made?** โ†’ adrs/ +- **What was planned for a given phase?** โ†’ phases/ +- **What's prioritized next?** โ†’ priorities/ diff --git a/plans/analysis-2026-07/01-executive-summary.md b/plans/analysis-2026-07/01-executive-summary.md new file mode 100644 index 0000000..b0bfcd8 --- /dev/null +++ b/plans/analysis-2026-07/01-executive-summary.md @@ -0,0 +1,49 @@ +# Executive Summary โ€” @nexcraft/forge Deep Analysis + +**Date:** 2026-07-13 ยท **HEAD analyzed:** `73f3b59` (develop, 2025-10-15) ยท **Method:** 41 AI agents across deep-read, adversarial fact-check, gap-probe, and synthesis phases (~2.8M tokens, 1,300+ tool calls). See [README](./README.md) for the document map. + +## The one-paragraph verdict + +Forge is a **genuinely substantial, functionally healthy, but abandoned and over-marketed** solo project. In a ~6-week sprint (Aug 28 โ€“ Oct 8, 2025, ~700 commits, 60 npm releases) it shipped 30 real web components with 100% test-file coverage (1,182 tests, all passing today), a working automated AI-metadata pipeline, 6 published npm packages, and an 18-ADR planning corpus โ€” then went dormant mid-firefight on 2025-10-15. Nine months later the toolchain still works end-to-end with zero fixes needed, but the README's headline claims are systematically false (coverage badge, "<10KB" bundle, "100% WCAG AA"), the "AI-native" differentiator is real at runtime but degraded in its shipped artifacts, distribution has a latent tree-shaking correctness hazard, 99 commits (including a security fix) were never released, and adoption is effectively zero (1 star, ~138 downloads/month). The project's own last planning doc candidly flagged the AI-native positioning as premature โ€” the remediation it proposed is, in essence, what this analysis recommends. + +## What's genuinely good + +- **The toolchain survived 9 months of dormancy untouched.** On 2026-07-13: type-check โœ…, lint โœ…, 1,147 unit + 35 a11y tests โœ… (19s), full build โœ…. `dist/`, `coverage/` are properly gitignored; git history is lean (16MB) with zero leaked secrets across 700 commits. +- **Every component implements real AI introspection.** `getPossibleActions()`/`explainState()`/`aiState` are meaningfully overridden in 30/30 components โ€” state-gated actions, real transitions โ€” and 19โ€“26 test files assert on them. This is the claim that survives adversarial review. +- **The metadata pipeline is automated, not hand-typed.** custom-elements-manifest โ†’ ai-manifest.json โ†’ ai-index.json, regenerated in CI, with a min-component gate. +- **Pockets of excellence:** modal's focus trap, multi-select's live-region announcements, checkbox/switch/radio-group's native-input a11y pattern, button's full 170-line AI metadata (the existence proof the other 29 components never got). + +## What's broken (ranked) + +1. **False public claims** โ€” coverage badge (real: 85.5%), bundle "<10KB" (real: 467KB / 91KB gzip; "selective imports" are shims that pull the whole bundle), "100% WCAG 2.1 AA" (real axe coverage: 5/29 components). These are refuted by the project's own artifacts. *Details: [09-fact-check](./09-fact-check.md).* +2. **Distribution correctness breakage** โ€” `sideEffects: false` + top-level `customElements.define` lets bundlers tree-shake component registration away entirely; **reproduced empirically with esbuild**, which strips the shim import and makes selective imports throw at runtime. Independently: `@nexcraft/forge/tooltip` throws even without a bundler, `@nexcraft/forge/utils` (2,129 LOC of documented utilities) has no exports entry and is unreachable, and the shims' `globalThis.NexcraftForge` lookup is dead code. ADR-011 designed the fix; never implemented. *Details: [04-testing-build-cicd](./04-testing-build-cicd.md), [02-architecture-and-ai-system](./02-architecture-and-ai-system.md).* +3. **Shipped-artifact quality gaps in the flagship AI system** โ€” ai-manifest categorizes every component as "atom"; a regex scraper silently degrades ~1/3 of components to placeholder actions; props conflate public API with private state; `ai-tools/` is exported in package.json but doesn't exist; the AI instruction files (`.cursorrules`, `claude-instructions.md`, copilot copy โ€” byte-identical triplicates) teach an import path removed in v0.9.0. *Details: [02-architecture-and-ai-system](./02-architecture-and-ai-system.md).* +4. **Fabricated documentation API surface** โ€” 40 of 43 "Public Methods" documented across the 7 organism doc pages don't exist; button/select/data-table docs contain invented props/events; 52 dead internal links (~22% of sample). *Details: [06-documentation-audit](./06-documentation-audit.md).* +5. **Real shipped bugs** โ€” tree-view selected/disabled styling never applies (CSS/template class drift); multi-select crashes on regex metacharacters in search; form-field's `aria-describedby` points at hardcoded IDs shaped around a test fixture; select re-triggers Lit update-after-update on every options change; button's `ghost`/`link` variants are unstyled; icon renders fetched SVG via `unsafeHTML` with no sanitization (latent XSS sink, currently unreachable). *Details: [03-component-inventory](./03-component-inventory.md).* +6. **Abandonment debt** โ€” 99 unreleased commits on develop incl. a Vite/esbuild security fix; 10 CI-green dependabot PRs open 5โ€“7.5 months; the nightly security workflow auto-disabled itself after 60 days of inactivity; local checkout 4 commits behind origin; npm `beta` dist-tag would downgrade users; TypeScript 2 majors behind. `npm audit`: 4 critical / 16 high โ€” **all confined to dev tooling and peer deps; zero ship in any published package's production tree** (verified). *Details: [05-packages-and-ecosystem](./05-packages-and-ecosystem.md).* +7. **Packaging/legal loose ends** โ€” forge-tokens and forge-mcp-figma published with **no license field and no LICENSE file** (SCA tools will flag them); forge-rhf accidentally bundles all of forge-react; forge-mcp-figma **does not speak MCP at all** (a real `initialize` handshake returns "Unknown method") despite its name and README; no `engines` field anywhere. +8. **Bus factor = 1, no succession** โ€” one personal npm account (`rollg`) owns all 6 packages; "dev-ignis" is a personal GitHub user, not an org; "Ignis Team" is a label; a single `NPM_TOKEN` secret publishes everything with no provenance. Live credentials (npm token + 3 Discord webhooks) sit in plaintext `.env` on disk โ€” never committed, but **rotate them**. + +## The numbers + +| Metric | Value | +|---|---| +| Components (registered custom elements) | 30 (+1 dev-tool) โ€” 14 atoms, 9 molecules, 7 organisms | +| Source / test / story LOC (components) | ~19.2K / ~13.1K / ~12.2K | +| Tests | 1,182 (all passing 2026-07-13); coverage 85.5% stmts | +| Published packages | 6 + core, all versions in sync with registry | +| Downloads (last month) | forge 138 ยท react 57 ยท rhf 57 ยท tokens 47 ยท angular 45 ยท vue 41 ยท mcp-figma 23 | +| GitHub | 1 star, 0 forks, 0 real issues, 10 stale dependabot PRs | +| Unreleased | 99 commits on develop (main is 1 ahead / 99 behind) | +| Activity | ~700 commits in 6 weeks by 1 human, then 0 human commits since 2025-10-15 (develop) / 2025-11-11 (main) | +| npm audit | 4C/16H/6M โ€” 0 in production dependency trees | + +## Decision framing + +Three viable paths (the recommended roadmap details each in [08-recommended-roadmap](./08-recommended-roadmap.md)): + +- **A. Revive properly** โ€” ~2โ€“4 weeks of focused work to make claims honest, fix the P0 bugs/packaging, ship the backlog, and make "AI-native" real where it's currently cosmetic. Worth it only if you'll actually use Forge in real projects or want it as a portfolio flagship. +- **B. Freeze honestly** โ€” ~2 days: rotate secrets, ship the security-fix backlog as a final release, correct the README's false claims, archive the repo, deprecate or notice the npm packages. Cheapest defensible end-state. +- **C. Status quo (do nothing)** โ€” costs nothing today, but leaves false advertising + a live npm token on disk + an unfixed security release sitting unpublished under your name. + +The one action recommended under **every** path, today: **rotate the npm token and Discord webhooks in `.env`** and re-issue the GitHub Actions secrets. diff --git a/plans/analysis-2026-07/02-architecture-and-ai-system.md b/plans/analysis-2026-07/02-architecture-and-ai-system.md new file mode 100644 index 0000000..64f9692 --- /dev/null +++ b/plans/analysis-2026-07/02-architecture-and-ai-system.md @@ -0,0 +1,202 @@ +# Forge โ€” Core Architecture & AI-Native System + +**Repo:** `@nexcraft/forge` v0.10.0 (Lit 3 web-component library), branch `develop`, dormant since 2025-10-15 (last commit). Published live on npm; verified against the actual 0.10.0 tarball, not just source. +**Scope of this section:** `src/core/`, `src/utils/`, `src/types/`, `src/tokens/`, `src/index.ts`, plus the AI-manifest generation pipeline (`scripts/generate-ai-manifest.js`, `generate-ai-index.js`, `validate-ai-manifest.js`, `ai-manifest.json`, `ai-index.json`, `custom-elements.json`). + +--- + +## TL;DR + +- **The core AI/perf/a11y contract in `BaseElement` is genuinely sound** โ€” `checkPerformance()`, `aiState`, `getPossibleActions()`/`explainState()` are real, working, reusable APIs (`src/core/BaseElement.ts`, 240 lines). The problem is never the base class; it's that adoption across the 29โ€“30 subclasses is 100% convention-based, with zero compiler or CI enforcement, and it has already fractured in practice. +- **Performance self-monitoring exists in four mutually incompatible forms** across components โ€” 10 call it correctly, 3 override it with an incompatible signature, 4 bypass it with a parallel reimplementation, 1 ignores the contract entirely. Net effect: `aiState.performance.renderCount`/`violations` is unreliable for roughly 2/3 of components, including Button and Input โ€” the two most likely to be inspected. +- **A meaningful slice of the published package is unreachable dead code.** `src/utils/**` (2,129 LOC: `TokenBridge`, `PerformanceDashboard`, debug console tools, error helpers) has no `exports["./utils"]` entry in `package.json` and is never bundled โ€” despite being documented as a primary API surface in the README and six doc guides. `AIMetadataExporter`/`AIMetadataValidator` (1,295 LOC, ~43% of `src/core`) are fully built but called by nothing, including the manifest-generation scripts they were seemingly built for. +- **A published subpath export is actively broken.** `@nexcraft/forge/tooltip` throws `Error: ForgeTooltip not found` at runtime because `ForgeTooltip` was never added to `src/index.ts`'s barrel, so it never made it into the bundle the subpath script inspects. +- **The AI-manifest pipeline is real, automated, and CI-regenerated โ€” but the shipped artifact undersells the runtime.** A brittle regex scraper (keyed on the TypeScript-only `override` keyword and one exact `return [...]` shape) silently degrades ~30% of components (โ‰ฅ9/31) to generic placeholder text in `ai-manifest.json`, even though every one of those components has a fully working `getPossibleActions()`/`explainState()` at runtime via `BaseElement`. +- **`ai-manifest.json`'s `category` field is uniformly wrong** โ€” every component reports `"atom"`, including organisms like `forge-data-table`, due to a one-line logic bug in the generator. +- **A referenced feature directory (`ai-tools/`) does not exist anywhere in the repo or the published tarball**, despite being wired into `package.json`'s `files`/`exports` and into `ai-index.json`'s own generated output โ€” a dead reference that will hard-fail on import. +- **Marketing claims ("FIRST AI-Native component library," "Every component can explain its state") are not fabricated but are measurably ahead of what ships.** The deepest architecture doc (`docs/ai/metadata-reference.md`) never reaches npm consumers; the schema file that's supposed to back validation is never loaded by the validator. + +--- + +## 1. Core architecture + +### 1.1 BaseElement โ€” single class, no mixins + +`src/core/BaseElement.ts` is a 240-line `abstract class BaseElement extends LitElement`. There is **no mixin composition** โ€” AI metadata, performance monitoring, and accessibility helpers are all hard-baked into one class rather than composed from smaller pieces. At this size that's not unmanageable, but it means every future cross-cutting concern gets bolted onto the same file rather than getting its own extension point. + +What it provides (all line-cited from `BaseElement.ts`): + +| Concern | Members | Lines | +|---|---|---| +| Shared styling | `static styles` (box-sizing reset) | 17-25 | +| AI-ready properties (cites **ADR-014**) | `semanticRole`, `aiContext`, `ariaDescription` | 28-30 | +| Performance properties | `maxRenderMs` (default 16), `warnOnViolation` (default **false**), `performanceMode: 'auto'\|'fast'\|'balanced'\|'quality'` | 33-35 | +| DX properties | `devMode`, `showMetrics` (the latter never read anywhere in `BaseElement.ts`) | 38-39 | +| `aiMetadata` default | `{ purpose: 'UI Component', criticality: 'low' }` | 47-50 | +| `checkPerformance(startTime)` | computes render time, increments `renderCount`, warns if over budget, triggers auto-degrade | 61-93 | +| `applyPerformanceDegradation()` | no-op stub โ€” subclasses must override to do anything | 96-98 | +| `get aiState()` | full AI-facing state snapshot | 101-129 | +| `getAIDescription()` / `getPossibleActions()` / `explainState()` | default implementations (`[]`, static stub) | 132-152 | +| `updateComponentState()` | writes to `componentState` Map, emits `ai-state-change` | 154-164 | +| `getSemanticAttributes()` | maps AI metadata to `data-*` attrs | 167-187 | +| `emit()` | `dispatchEvent` wrapper, `bubbles/composed/cancelable: true` by default | 189-198 | +| `announceToScreenReader()` | off-screen `aria-live` region on `document.body` | 201-213 | +| `firstUpdated()` | sets `data-ready="true"` | 216-219 | +| `trapFocus()` | Tab-key focus trap | 222-240 | + +**`checkPerformance()` is a real, working, reusable API** โ€” this is worth stating explicitly, because it's easy to misread the fractured adoption (ยง1.2) as "the base class doesn't provide performance monitoring." It does; components just don't consistently use it. + +**No dedicated test exists for `BaseElement` itself.** `find . -iname "*BaseElement*"` turns up only the source file and generated coverage/storybook artifacts โ€” no `BaseElement.test.ts`. The class shows 90.41% statement coverage (151/167) in the last pre-dormancy coverage run (2025-10-03, 12 days before the final commit), but that coverage is a **side effect** of 26 component test files exercising inherited methods incidentally, not a test that asserts `BaseElement`'s own contract (e.g., nothing directly verifies `checkPerformance`'s math or the auto-degrade trigger). + +Two members are confirmed dead: +- **`trapFocus()` is never called by any component.** It's the one method marked "not covered" in the coverage report, and `grep -rln trapFocus src/components --include=*.ts | grep -v test` returns zero hits across all 29 components that inherit it. +- **`announceToScreenReader()` is called by exactly 1 of 29 components** (`button.ts`). + +### 1.2 Performance monitoring โ€” a sound contract, fractured adoption + +`checkPerformance()` is opt-in: `BaseElement` never calls it automatically from its own lifecycle, so a subclass has to invoke it from its own `render()`/`updated()`. In practice, adoption split into **four incompatible patterns**, independently confirmed with file:line citations: + +| Pattern | Behavior | Components | +|---|---|---| +| **A โ€” Correct** | Calls inherited `checkPerformance(startTime)` with matching signature | `radio-group.ts:342,536`, `switch.ts:362,496`, `card.ts:456`, `select.ts:779`, `date-picker.ts:841`, `tooltip.ts:524`, `dropdown.ts:739`, `modal.ts:555`, `multi-select.ts:750`, `data-grid.ts:1083` (10 components) | +| **B โ€” Signature-incompatible override** | Redefines `checkPerformance` to take an already-computed *duration* instead of a *start time* โ€” TS doesn't catch it because both erase to `(number) => void`. Keeps its own `renderMetrics` object instead of `this.renderCount`, so the inherited counter never increments. | `button.ts:542` (called `button.ts:386`), `input.ts:478` (called `input.ts:364`), `form-field.ts:516` (called `form-field.ts:314`) (3 components) | +| **C โ€” Parallel reimplementation, bypasses base entirely** | Own private `trackRenderPerformance(startTime)` duplicating the budget-check logic, with shadowed `maxRenderMs`/`renderTime` fields | `badge.ts`, `alert.ts`, `icon.ts`, `checkbox.ts` (4 components) | +| **D โ€” Wholly custom scheme** | Own `performanceThreshold` property (not `maxRenderMs`), no-arg `trackRenderPerformance()`, never touches the base contract at all | `data-table.ts` (1 component) | + +That's 18 of ~29-30 components touching performance tracking in *some* form; the rest wire up nothing. **Root cause is structural, not accidental**: nothing enforces subclasses call `checkPerformance` from `render`/`updated`, and TypeScript's structural typing permits any `(number) => void` override to silently replace the base method. + +**Concrete consequence โ€” the `aiState.performance.violations` bug.** `BaseElement.ts:110` hardcodes `violations: 0` in the `aiState` getter; it never reads an actual violation counter. 12 components override the `aiState` getter and presumably fix this locally. The 10 components using Pattern B or C (`switch`, `icon`, `badge`, `radio-group`, `alert`, `select`, `button`, `checkbox`, `input`, `form-field`) do **not** override `aiState`, so `component.aiState.performance.violations` reports `0` for them even when the component's own template shows a live, correct violation count (`button.ts:395` renders `${this.renderMetrics.violations}` in its dev UI while `button.aiState.performance.violations` โ€” the value any AI agent or the dashboard would actually consume โ€” always says 0). This directly undermines the "AI-native, machine-readable state" pitch for exactly the components (Button, Input, FormField) most likely to be inspected first. + +### 1.3 AI metadata layer โ€” convention-enforced, not type-enforced + +`getPossibleActions()`, `explainState()`, and the `aiState` getter are all **non-abstract members with working default implementations**. `BaseElement` is "abstract" only in the sense that it can't be instantiated directly โ€” nothing stops a new subclass from never overriding these and silently shipping an AI-native-labeled component with `possibleActions: []` and a generic `'default'` state description. + +- **Today, discipline holds**: all 30 current `BaseElement` subclasses override both methods, and git history shows this was a deliberate, tracked milestone (`c46d3c1 feat: complete AI methods implementation for all components`). +- **But it's unenforced going forward**: no lint rule, no abstract method, no test scanning registered custom elements for AI-method coverage. `scripts/generate-ai-manifest.js` parses source via regex โ€” it doesn't validate or gate (see ยง2). +- **`aiMetadata` fallback**: of 29 direct `BaseElement` subclasses, **10 never override the protected `aiMetadata` field** and keep the literal default `{ purpose: 'UI Component', criticality: 'low' }` at runtime: `checkbox.ts`, `tree-view.ts`, `navigation-bar.ts`, `pagination.ts`, `badge.ts`, `icon.ts`, `alert.ts`, `accordion.ts`, `tabs.ts`, `data-table.ts`. +- **Button's static/instance metadata disconnect (a genuine, verified bug)**: `button.ts:14-~90` declares a rich `static aiMetadata: AIComponentMetadata` field (purpose string, usage patterns, anti-patterns, contextual rules, AI prompts) โ€” clearly meant as Button's real AI-facing metadata. But `BaseElement.aiState`, `getAIDescription()`, and `getSemanticAttributes()` all read the **instance** field `this.aiMetadata` (`BaseElement.ts:47,119,134,178-184`), and Button never bridges the two (it only mutates `this.aiMetadata.semanticRole` at runtime, `button.ts:434`). Net effect: `document.querySelector('forge-button').aiState.metadata.purpose` returns the generic "UI Component" fallback, not Button's carefully authored purpose text โ€” despite that text sitting in the same file, unused by the runtime API this whole system is supposedly built around. + +### 1.4 Export surface โ€” components and utilities that don't reach consumers + +Three separate, independently-verified breakages, all confirmed against the actual published npm tarball for 0.10.0 (not just source): + +1. **`@nexcraft/forge/tooltip` is broken.** `ForgeTooltip` (`src/components/molecules/tooltip/tooltip.ts`) is a complete, tested component โ€” but it's absent from `src/index.ts`'s molecule export block (lines 74-103), so it's never in the main bundle. `package.json`'s `exports` map still has a `"./tooltip"` subpath whose generated shim (`scripts/build-exports.cjs`) does `customElements.get('forge-tooltip') || throw new Error('ForgeTooltip not found...')`. Confirmed: zero occurrences of `ForgeTooltip`/`forge-tooltip` in the actual `dist/nexcraft-forge.es.js` bundle. Importing this subpath from the published package throws at runtime. +2. **`@nexcraft/forge/utils` doesn't exist as an export, despite being the documented way to import core utilities.** README.md (lines 145, 319, 344) and six doc guides tell users to import `TokenBridge`, `performanceDashboard`, `enableGlobalDebug`/`debugComponent`/`watchComponent`, `showToast` from `@nexcraft/forge/utils`. There is no `"./utils"` key in `package.json`'s `exports` map (verified against the live registry too), and `vite.config.ts`'s single-entry build never pulls from `src/utils/**`. `dist/utils/` only has `.d.ts` files โ€” zero runtime `.js`. Everything in `src/utils/**` (`TokenBridge`, `PerformanceDashboard`, debug tools, `errors.ts` helpers โ€” 2,129 non-test LOC, unit-tested, described as "critical for developer experience" and a "key UVP differentiator" in their own file headers) is **completely unreachable from the published package.** +3. **`AIMetadataExporter` (734 LOC) and `AIMetadataValidator` (561 LOC) โ€” 1,295 LOC, ~43% of all non-test `src/core` code โ€” are dead from every angle**: not exported from `src/index.ts`, not called by `scripts/generate-ai-manifest.js` (which does its own independent regex parsing instead of calling `AIMetadataExporter.exportTrainingDataset()`), not called by `scripts/validate-ai-manifest.js` (which does its own shallow 3-field check instead of `AIMetadataValidator.validateComponentMetadata()`), and not imported by any test file. Well-designed, substantial, and entirely disconnected from anything that runs. + +### 1.5 Design-token bridge โ€” three uncoordinated implementations + +- `src/tokens/base.css` (129 LOC) is the one static artifact that actually ships and works end-to-end: hard-coded `--forge-color-*` custom properties, copied to `dist/tokens.css` by a Vite `writeBundle` hook (`vite.config.ts:78-90`), exposed via the `"./tokens.css"` export. It also documents a past naming migration in-line (both `--forge-color-danger-500` and legacy `--forge-color-error` coexist). +- `src/utils/token-bridge.ts`'s `TokenBridge` class (613 LOC) is a separate converter (Figma/Tailwind/Material Design JSON โ†’ Forge token shape) targeting the same `--forge-${name}` naming convention conceptually, but with no test asserting the two agree, and โ€” per ยง1.4 โ€” entirely unreachable from the published package anyway. +- A third, standalone published package, `packages/forge-tokens`, has its own CLI (`bin/forge-tokens.mjs`) and Figma integration (`lib/figma.mjs`), duplicating the same "convert design tokens into Forge tokens" problem a third time (out of this section's scope, flagged for whoever covers `packages/**`). + +### 1.6 SSR, types, and event-naming โ€” smaller but real issues + +- **SSR is a keyword, not a capability.** `package.json` lists `"ssr"` only in the marketing `keywords` array; `@lit-labs/ssr` is not a dependency. `ForgeIntegrationConfig.enableSSRFallbacks?: boolean` (`src/types/framework-integration.ts:24`) is declared and JSDoc'd but never read anywhere in `src/**`. The one actively SSR-unsafe piece of code that does exist โ€” `PerformanceDashboard`'s constructor eagerly touching `document.body` at **module-evaluation time**, not inside a lifecycle hook (`performance-dashboard.ts:50-77`) โ€” is currently moot only because `src/utils` is unreachable from the package (ยง1.4); it would resurface the moment someone "fixes" the missing `./utils` export. +- **`ForgeElement` interface is structurally unsatisfiable by `BaseElement`.** `ForgeElement` (`types/component-types.ts:10-17`) declares `emit`/`announceToScreenReader` as implicitly-public members; `BaseElement` implements both as `protected`. No real subclass instance can be assigned to a `ForgeElement`-typed variable without a compile error โ€” confirmed never attempted anywhere in `src/**`, so the incompatibility has never been caught. +- **Duplicate `debounce`/`throttle`**, and the worse one ships. `src/types/component-types.ts:98-126` has a basic version (no `immediate`, no `raf`); `src/utils/debounce.ts` has a fuller version โ€” but it's unreachable (ยง1.4), so the public `src/index.ts` re-exports the simpler one. +- **`Forge*Events` TypeScript interfaces don't describe what components actually emit.** They declare a `forge-`-prefixed convention (`forge-click`, `forge-open`, `forge-dismiss`, etc.), but grepped runtime behavior shows: `ForgeButton` emits `'click'`; `ForgeModal` emits a single unprefixed `'modaltoggle'`; `ForgeAlert` dispatches `'close'` via a hand-rolled `CustomEvent` at `alert.ts:328-335`, bypassing `BaseElement.emit()` entirely. Only two literal `forge-`-prefixed events exist anywhere in the codebase (`forge-change`, `forge-select`). Any consumer relying on the exported `Forge*Events` types for typed `addEventListener` gets wrong autocomplete with no compile-time safety. + +### 1.7 Coupling and residual dead code + +- **`PerformanceDashboard` depends on an undocumented `BaseElement` contract.** Its auto-discovery (`performance-dashboard.ts:80`) scans for `[data-ready="true"]` plus `instanceof BaseElement` โ€” `data-ready` is set exactly once, in `BaseElement.firstUpdated()` (`BaseElement.ts:216-219`). This coupling is real and functional but is discoverable only by reading `performance-dashboard.ts`; nothing in `BaseElement.ts` itself documents that another module depends on this attribute. +- **`ai-manifest.json` generation is coupled to source text, not to the type system.** `scripts/generate-ai-manifest.js` depends on the exact textual shape of `getPossibleActions`/`explainState` overrides (regex against raw `.ts` source) rather than on the typed `AIAction`/`AIStateExplanation` contracts already defined in `ai-metadata.types.ts` โ€” an out-of-band coupling between build tooling and source formatting that a normal refactor (e.g., reformatting a `return` statement) can silently break. +- **Duplicate AI-metadata test suites.** `src/core/ai-metadata.test.ts` (683 LOC) and `src/test/ai-metadata.test.ts` (295 LOC) both `describe('AI Metadata System', ...)` and both test `AIMetadataUtils` โ€” overlapping coverage in two different directories, suggesting a stale draft left alongside its replacement rather than a deliberate split. Not determined which (if either) is authoritative. +- **`warnDeprecated()`** (`src/utils/errors.ts:177-194`) is a built, generic deprecation-warning helper with zero call sites anywhere in `src/components` โ€” built for a future deprecation cycle that never arrived, consistent with a young API surface rather than a bug. +- **`src/simple.test.ts`** sits directly under `src/`, outside both `src/core` and `src/test` โ€” a minor stray/misplaced test file, not investigated further. + +--- + +## 2. AI-native metadata system + +### 2.1 Pipeline โ€” genuinely automated, with two hand-maintained pockets + +``` +custom-elements-manifest analyze โ†’ custom-elements.json (real AST-based CEM output, git-ignored, rebuilt at publish) +scripts/generate-ai-manifest.js โ†’ ai-manifest.json (regex re-shapes CEM output; fails hard if <30 components found) +scripts/generate-ai-index.js โ†’ ai-index.json (compact summary of the manifest) +scripts/validate-ai-manifest.js โ†’ exit 0/1 (checks only that 3 top-level fields have the right JS type) +``` + +This is real, tool-derived output, not hand-typed JSON โ€” `custom-elements.json` is a legitimate CEM/Lit-plugin AST analysis (1.38MB, captures real `@property` fields, JSDoc, `privacy`, `attribute` names, `default` values). But two large pieces are hand-authored and structurally disconnected from source: + +- **`a11yMappings`** (`generate-ai-manifest.js:110-381`) โ€” a ~270-line hardcoded per-component ARIA lookup table, unconnected to each component's actual rendered template. +- **`ssrFallbacks`** (lines 452-568) โ€” hardcoded HTML strings per component tag, likewise hand-authored. +- **`extractAIMethodImplementations`** (lines 20-103) โ€” a regex scraper of raw `.ts` source text, not an AST pass (see ยง2.2). + +`validate-ai-manifest.js` never loads `ai-manifest.schema.json` โ€” confirmed by grep โ€” despite the README calling it "Schema validation." It's a ~35-line script whose own header comment says it "exits 0 to avoid breaking CI initially." + +### 2.2 The extraction gap โ€” ~30% of components silently degrade + +`extractAIMethodImplementations` requires the literal substring `override getPossibleActions()` (a TypeScript-only compile-time keyword with zero runtime effect) followed by a specific `return [ {...} ];` array-literal shape: + +```js +const actionsMatch = sourceContent.match(/override getPossibleActions\(\)[^{]*\{([\s\S]*?)\n \}/); +``` + +- Of 30 files with a real `getPossibleActions(` implementation, only 21 use the `override` keyword. The other **9** (`date-picker.ts`, `multi-select.ts`, `card.ts`, `input.ts`, `tooltip.ts`, `modal.ts`, `dropdown.ts`, `button.ts`, `form-field.ts`) get silently replaced with generic placeholder text in the shipped manifest, despite having real, richer runtime behavior. **`button.ts` โ€” the most commonly inspected component โ€” is one of them.** +- Even when `override` is present, the second regex requires a literal `return [...]` array. `forge-data-table.ts:821` has `override getPossibleActions()` but builds its actions dynamically (`push()` in loops/conditionals) โ€” arguably the more idiomatic pattern for a data-heavy component โ€” and gets zero extracted actions anyway. +- Only 2 of 5 spot-checked components (`checkbox`, `alert`) extracted faithfully; `button` and `modal` fell back to generic text (missing `override`); `data-table` fell back despite having `override` (dynamic-array shape). +- **This is purely a static-manifest problem.** At runtime, every component's `getPossibleActions()`/`explainState()`/`aiState` genuinely work (they all extend `BaseElement`). An AI agent driving a live DOM gets correct data; an AI tool statically reading `ai-manifest.json` โ€” which the README explicitly recommends ("AI: [Reads ai-manifest.json] โ†’ Gets forge-button props") โ€” gets the degraded version for ~30% of components. + +### 2.3 Other manifest defects + +| Defect | Detail | +|---|---| +| **`category` always `"atom"`** | `generate-ai-manifest.js:585`: `category: d.customElement ? 'atom' : undefined` โ€” `d.customElement` is truthy for every CEM entry reaching that branch, so it's always `"atom"`, including `forge-modal` (molecule), `forge-data-table` (organism). The repo's own atoms/molecules/organisms taxonomy is never consulted. `ai-index.json`'s category summary is consequently meaningless. | +| **Props conflate public/private** | `generate-ai-manifest.js:586-588` filters CEM members only on `kind === 'field'/'property'`, never on `privacy`. Checked `forge-alert`: 8 of 25 listed "props" are `private`/`protected` internals (`closing`, `dismissTimer`, `iconMap`, `performanceStartTime`, `renderTime`, `renderCount`, `aiMetadata`, `componentState`), indistinguishable in the manifest from real public props like `severity`/`message`. | +| **`default`/`required`/`description` dropped** | `custom-elements.json` has this data (verified: `severity default='info'`, etc.), and `ai-manifest.schema.json` defines a `default` field per prop โ€” but the `.map()` never copies it over. 0/31 components have a populated schema-promised field. | +| **a11y table drift + gaps** | `forge-button`'s hardcoded entry claims `aria-pressed` and `aria-describedby`; the actual template (`button.ts:352-371`) has neither โ€” it emits `aria-description` (nonstandard) instead. The table has exactly 30 entries for 31 shipped components; the 31st (`forge-performance-dashboard`, picked up because the CEM glob is broad) silently falls to a generic default. | +| **`ai-tools/` doesn't exist** | Referenced in `package.json` `files` and `exports["./ai-tools/*"]`, and in `ai-index.json`'s own `aiIntegration.functionCalling: './ai-tools/'` field โ€” but the directory exists nowhere in the repo, `dist/`, or the published tarball (verified via both `npm pack --dry-run` and the real downloaded 0.10.0 tarball). `import '@nexcraft/forge/ai-tools/whatever'` hard-fails. Consistent with a rushed buildout โ€” the AI infra commits cluster in a single week, 2025-09-17. | +| **`docs/ai/` never ships** | `docs/ai/metadata-reference.md` (678 lines) and `docs/ai/integration-guide.md` (1,063 lines) โ€” the deepest architecture explanation of this whole system โ€” are absent from `package.json`'s `files` allowlist, confirmed absent from the real tarball. What ships instead (`docs/guides/ai-native-development.md` etc.) is a shallower usage guide. | + +### 2.4 CI โ€” regenerates fresh, but doesn't gate on fidelity + +`.github/workflows/ci.yml` and `develop.yml` both run the full `build:manifest โ†’ build:ai โ†’ validate:ai` chain on every push, so `custom-elements.json`/`ai-manifest.json`/`ai-index.json` are freshly regenerated from current source each time, and the generator's `expectedMinComponents = 30` gate (`generate-ai-manifest.js:633-650`) would catch total extraction failure. But: +- `validate:ai` only type-checks 3 top-level fields โ€” it never checks per-component content (it would never flag Button's empty actions array). +- No workflow step diffs the regenerated manifest against the committed one (`grep -n "git diff\|--exit-code" .github/workflows/*.yml` โ†’ nothing). +- `ai-manifest.json`/`ai-index.json` are committed to git; `custom-elements.json` is git-ignored but rebuilt at publish. The last manifest commit (2025-10-08) does line up correctly with the 0.10.0 publish date, so *this* release was regenerated properly before shipping โ€” but nothing forces that discipline going forward, and the `override`-keyword gap has evidently existed silently since the September 2025 buildout with no fix. + +### 2.5 Marketing vs. verified reality + +README claims: "**The FIRST AI-Native component library**," "Every component can explain its state to AI systems," "AI-Native Components (Industry First!)" with a badge linking to `docs/ai/metadata-reference.md` โ€” which, per ยง2.3, never reaches npm consumers, so the badge only works for people browsing GitHub directly. Line-count claims for `ai-index.json`/`ai-manifest.json` ("465 lines" / "2000+ lines") are stale/imprecise (actual: 473 / 5,465) but not false. "Browse all 31 components" is accurate. + +**Verdict**: not vaporware. There's a real, automated, source-derived generation pipeline, and every one of the 31 shipped components genuinely has working runtime AI introspection via `BaseElement`. But the specific artifact given its own npm subpath and positioned as the AI-native centerpiece โ€” `ai-manifest.json` โ€” is measurably less complete than its own README and JSON schema promise: ~30% of components have degraded action data, `category` is wrong for everything, props don't distinguish public from private, a referenced feature directory doesn't exist, and the deepest documentation of the system doesn't ship. The gap is specifically between two consumption modes: an AI tool that **instantiates a live component and calls `.explainState()` directly** gets accurate data; an AI tool that **statically reads the shipped JSON** (the mode the README recommends) does not. + +--- + +## 3. Strengths + +- **The core contract is well-designed.** `BaseElement`'s `checkPerformance`/`aiState`/`getPossibleActions`/`explainState` API is coherent, reasonably sized, and โ€” where adopted correctly โ€” works as advertised. This is not a case of the architecture being broken; it's a case of adoption discipline having nothing to enforce it. +- **The AI-manifest pipeline is real engineering, not a mock.** AST-based CEM analysis, a hard-fail component-count gate, CI regeneration on every push โ€” this is a legitimate automated toolchain, unusual for a project at this stage. +- **In-practice discipline was genuinely good while the project was active.** All 30 current components implement the AI-method convention; git history shows it was a deliberate, tracked milestone, not an accident. +- **The static CSS token layer (`src/tokens/base.css` โ†’ `dist/tokens.css`) is a small, simple, fully-working deliverable** with no dependency on the more ambitious (and broken) `TokenBridge`/`ai-tools` layers. +- **No TODO/FIXME/HACK markers anywhere in `src/core`, `src/utils`, `src/types`.** The staleness here is structural (dead exports, drifted metadata) rather than abandoned inline work โ€” a dormant codebase that was left in a deliberately-committed state, not mid-edit. + +## 4. Weaknesses & risks (ranked) + +1. **No CI/type-level enforcement of the AI-method contract.** A dormant project resuming development has zero automated signal telling a new contributor to implement `getPossibleActions`/`explainState`, or telling them their implementation doesn't match the manifest generator's regex shape. This is the highest-leverage fix relative to effort โ€” it protects the project's entire stated value proposition. +2. **The shipped `ai-manifest.json` misrepresents ~30% of components and the category of all of them**, while a fully accurate runtime alternative already exists (`BaseElement.aiState`). This is a credibility risk specifically for the "AI-native" positioning: it's the artifact most likely to be evaluated first by anyone doing exactly the kind of due diligence this document represents. +3. **`@nexcraft/forge/utils` and `@nexcraft/forge/tooltip` are broken/unreachable in the currently-published package**, contradicting the README. Anyone following the docs today hits a runtime error or silent 404. This is a trust-eroding first-contact bug for new adopters, cheap to fix (add the missing `exports` entries and confirm the tooltip barrel export). +4. **Performance self-monitoring's 4-pattern fracture** means `aiState.performance` is untrustworthy for the majority of components, including the ones most likely to be profiled (Button, Input, FormField). Low urgency for typical usage, but directly undermines a headline feature if anyone actually wires up the dashboard. +5. **1,295 LOC of well-built, fully dead code** (`AIMetadataExporter`, `AIMetadataValidator`) and **2,129 LOC of fully-implemented-but-unreachable utilities** represent real sunk engineering that isn't currently delivering value and will rot further the longer the project stays dormant (APIs drift from whatever calls them once someone tries to wire them back in). +6. **Three uncoordinated "design token" implementations** (`base.css`, in-repo `TokenBridge`, standalone `packages/forge-tokens`) โ€” a maintainability risk if revival work touches tokens without first deciding which one is canonical. +7. **`ai-tools/` is a dead reference that will hard-fail on import** โ€” low probability of anyone hitting it today (nothing documents *using* it directly), but it's exactly the kind of stale pointer that causes confusing bug reports months into a revival. +8. **Type-soundness gaps (`ForgeElement` interface, duplicate `debounce`/throttle, inconsistent event names) are pre-existing technical debt**, not urgent, but will surface as confusing compiler errors or wrong autocomplete the moment someone tries to use the public types as documented. + +## 5. Section-specific recommendations + +**If reviving the AI-native positioning as the core value proposition:** +- Rewrite `extractAIMethodImplementations` as an AST-based extraction (the CEM analyzer already parses the file โ€” reuse its AST instead of re-scraping raw text with regex) rather than patching the regex; the current approach will keep breaking on any code-style change. +- Fix the one-line `category` bug (`generate-ai-manifest.js:585`) by consulting the actual `src/components/{atoms,molecules,organisms}` directory structure. +- Wire `validate-ai-manifest.js` to actually load `ai-manifest.schema.json` (the comment already says this was the plan) and add a CI step that diffs the regenerated manifest against the committed one, failing the build on drift. +- Decide whether `AIMetadataExporter`/`AIMetadataValidator` are worth resurrecting (call them from the actual generation/validation scripts) or worth deleting โ€” right now they're 1,295 LOC of maintenance liability with no dependents. + +**If reviving the component library as a general-purpose Lit library (AI story secondary):** +- Prioritize #3 above (`./utils` and `./tooltip` exports) โ€” these are the cheapest, highest-visibility fixes and directly contradict current documentation. +- Consolidate performance monitoring onto Pattern A before adding any new components; either delete `applyPerformanceDegradation()`'s no-op default or make `checkPerformance` abstract-like via a lint rule so new components can't silently skip it. +- Pick one of the three token systems as canonical and deprecate the other two explicitly, rather than letting a fourth "helpful" implementation get added later. + +**Either way:** +- Add a `BaseElement.test.ts` that asserts the base contract directly (perf math, `aiState` shape, the `violations` field) โ€” current coverage is 100% incidental, so any refactor of `BaseElement` itself has no dedicated safety net. +- Treat the gap between "runtime introspection works" and "shipped static manifest is degraded" as the single most important fact to communicate to any future contributor or evaluator โ€” it's the difference between a legitimate technical claim and a misleading one, and right now the misleading version is what's on npm. diff --git a/plans/analysis-2026-07/03-component-inventory.md b/plans/analysis-2026-07/03-component-inventory.md new file mode 100644 index 0000000..b9d7cca --- /dev/null +++ b/plans/analysis-2026-07/03-component-inventory.md @@ -0,0 +1,242 @@ +# Component Inventory โ€” @nexcraft/forge v0.10.0 + +Repo: `/home/air_buster/rollg/ignis/apps/forge`. Branch `develop`, last commit `73f3b594e` on +2025-10-15 (dormant ~9 months as of 2026-07-13). Single-author project +(`ignis `) โ€” effectively a solo effort, not a team-maintained library. + +## TL;DR + +Forge ships **30 distinct custom elements** (14 atoms, 9 molecule-tier elements across 8 +directories, 7 organisms) โ€” not the 27 the README claims (`README.md:434,520` says "12 atoms, 8 +molecules, 7 organisms"; the atoms directory actually has 13 folders / 14 elements, and the +organism count is contradicted between two sections of the same README). Engineering quality is +genuinely uneven but not bad: **every component has a passing test file and a Storybook file** +except `data-grid`, which has zero stories despite being the single largest, most complex file in +the repo (1,189 LOC). All 528 atom tests pass; no `.skip`/`.only` tests exist anywhere in atoms or +molecules. + +The headline risk for anyone reviving this project is **not code rot, it's trust in the +"AI-native" pitch**. Three things undercut it hard: (1) two real, unsanitized-HTML injection +points (`forge-icon`'s SVG loader, `forge-tooltip`'s `htmlContent` mode) that are live XSS vectors +if fed untrusted input; (2) the component docs (`docs/components/**/*.md`) are **systematically +fabricated** โ€” across all 7 organisms, only 3 of 43 documented "public methods" actually exist and +match their documented signature; (3) the generated `ai-manifest.json` mis-categorizes every +molecule and organism as `"category": "atom"`, invents at least one ARIA role, and goes stale (it +wasn't regenerated after `forge-card`'s `border` prop was added). None of this is exotic โ€” it's +the kind of drift you get from a solo project moving fast for ~6 weeks and then stopping cold. + +Below: full inventory table, per-component notes (issues only โ€” see the source analyst notes for +full behavioral descriptions), cross-cutting patterns, a severity-ranked bug list, and +recommendations. + +## Component Inventory (all 30 elements) + +| Component | Tier | LOC | Props / Events / Slots | AI metadata depth | Tests | Stories | Notable issues | +|---|---|---|---|---|---|---|---| +| `forge-alert` | atom | 485 | 16 / 1 / 2 | Stub (never sets `aiMetadata`) | 24 pass | yes | Duplicated perf-overlay code; not on project's own perf-warning TODO list but shares the root cause | +| `forge-aspect-ratio` | atom | 361 | 6 / 0 / 1 | Static + custom `aiState` | 45 pass | yes | JS-only object-fit application misses late-slotted content; no perf overlay at all | +| `forge-avatar` | atom | 437 | 10 / 1 / 0 | Reactive, populates `componentState` | 23 pass | yes | Dead `avatar/index.ts` barrel (127 B, unused) | +| `forge-badge` | atom | 503 | 18 / 0 / 1 | Stub | 34 pass | yes | Named in project's own unresolved Lit perf-warning TODO; imperative `style.transform` animation bypasses Lit | +| `forge-button` | atom | 568 | 15 / 1 / 1 | **Full static AI metadata (only atom)** | 47 pass | yes | `variant="ghost"/"link"` has no CSS; `PerformanceMode` type mismatch vs. `BaseElement`; ripple-id collision risk | +| `forge-checkbox` | atom | 538 | 20 / 2 / 0 | Stub | 32 pass | yes | Named in perf-warning TODO; largest prop count, 8 are duplicate `BaseElement` fields | +| `forge-icon` | atom | 588 | 14 / 0 / 0 | Stub (despite being the most-reused atom) | 20 pass | yes | **`unsafeHTML(svg)` from arbitrary fetched URL โ€” real XSS vector** (icon.ts:400); named in perf-warning TODO | +| `forge-input` | atom | 645 | 21 / 7 / 2 | Reactive, populates `componentState` | 57 pass | yes | Incompatible `checkPerformance()` override signature vs. base class | +| `forge-progress` | atom | 351 | 6 / 0 / 1 | Static + custom `aiState` | 24 pass | yes | Slot-content detection via raw `innerHTML` string read, not `slotchange` | +| `forge-progress-circle` | atom | 420 | 9 / 0 / 1 | Static + custom `aiState` | 32 pass | yes | Same slot-detection smell as `progress`; awkward 2-boolean label API | +| `forge-radio-group` | atom | 564 | 12 / 2 / 0 | Static + `getAIDescription()` | 38 pass | yes | Correctly reuses base perf logic but still carries the dead duplicated CSS block | +| `forge-select` | atom | 830 (largest atom) | 15 / 4 / 0 | Static + `getAIDescription()` | 42 pass | yes | **`aria-labelledby`/`aria-describedby` reference IDs that don't exist in the template**; reproduced the live "scheduled update after completion" Lit warning during the test run | +| `forge-skeleton` | atom | 259 (smallest atom) | 6 / 0 / 0 | Static + custom `aiState` (incl. live computed size) | 33 pass | yes | Dead CSS `attr()` rule, confirmed non-functional by live browser test (Chrome 142, Firefox 136) โ€” harmless, JS path overrides it | +| `forge-switch` | atom | 521 | 13 / 2 / 0 | Static + `getAIDescription()` | 46 pass | yes | Cleanest atom overall; still carries the dead duplicated perf-overlay CSS | +| `forge-card` | molecule | 528 | 14 / 2 / 5 | Rich static | 25 pass | yes | `expand` AI action hard-coded `available: false`; 4 dead "has-slot" state fields never consumed in render | +| `forge-date-picker` | molecule | 935 (largest molecule) | 14 / 1 / 0 | Rich static, **inaccurate** | 46 pass | yes | AI metadata claims `ArrowKeys` support that doesn't exist in code; no focus trap on calendar dialog; zero keyboard tests | +| `forge-dropdown` | molecule | 815 | 10 / 2 / 0 | Rich static, accurate | 71 pass (largest test suite) | yes | DOM focus never moves during keyboard nav, no `aria-activedescendant`; mismatched `combobox`+`menu` ARIA roles | +| `forge-form-field` | molecule | 549 | 20 / 4 / 0 | Thinner (2-entry `interactions`) | 35 pass | yes | **Hardcoded literal `aria-describedby` IDs shipped to every real instance regardless of `name`** โ€” broken for real usage, tests pass only because the fixture is literally named "accessible" | +| `forge-modal` | molecule | 623 | 13 / 2+legacy / 3 | Rich static | 27 pass | yes | Best focus trap in the library; `getPossibleActions()` advertises a `toggle()` method that doesn't exist | +| `forge-multi-select` | molecule | 848 | 10 / 1 (5 dispatch sites) / 0 | Rich static, goes stale | 30 pass | yes | **Unescaped regex from user search input throws `SyntaxError`** on any regex metacharacter โ€” untested | +| `forge-toast` | molecule | 604 | 8 / 2 / 3 | Thin `getPossibleActions()`, deepest `@csspart` docs | present | shared w/ container | Emoji default icons, no `aria-hidden`/text fallback; dual dismiss events (one deprecated, still current at v0.10.0) | +| `forge-toast-container` | molecule | 435 | 3 / โ€” / โ€” | Thin | present | shared w/ toast | Global `window.forgeToastContainer` singleton pattern | +| `forge-tooltip` | molecule | 586 | 10 / 1 / 1 | Rich static, accurate role | 28 pass | yes | **Unsanitized `.innerHTML=` bind when `htmlContent=true` โ€” live XSS vector**, untested; duplicate/likely-dead `aria-describedby` on host | +| `forge-accordion` | organism | 263 (smallest organism) | 3 / 1 / โ€” | `aiState` only (generic metadata) | 22 pass | yes | `expandAll()`/`collapseAll()` advertised as AI actions but never called anywhere (private, unreachable); docs 0/6 methods verified | +| `forge-data-grid` | organism | 1,189 (largest of all 30) | 16 / 9 / โ€” | **Only organism with full static `aiMetadata`** | 54 pass (most of any organism) | **none โ€” zero stories** | Missing from `organisms/index.ts` barrel; column resize is a no-op stub; own local `VirtualScroller` (2nd incompatible implementation in repo) goes stale on filter/sort; docs 0/9 methods verified | +| `forge-data-table` | organism | 926 | 16 / 2 / โ€” | `aiState` only | 17 pass (thinnest ratio) | yes | Imperative DOM manipulation bypasses Lit render (hardcoded placeholder `` briefly visible); virtual scroller never told about data changes; docs: default value inverted, 3 fabricated events, 0/6 methods verified | +| `forge-navigation-bar` | organism | 668 | 9 / 2 / โ€” | `aiState` only | 37 pass | yes | Docs 0/3 methods verified (2 exist but private) | +| `forge-pagination` | organism | 635 | 12 / 2 / โ€” | `aiState` only | 23 pass | yes | Docs 0/6 methods verified (1 exists but private) | +| `forge-tabs` | organism | 626 | 7 / 3 / โ€” | `aiState` only | 26 pass | yes | Drag-reorder and lazy-loading are genuinely implemented (not stubs); docs 0/4 methods verified | +| `forge-tree-view` | organism | 905 | 6 / 2 / โ€” | `aiState` only | 30 pass | yes | **Selected/disabled visual states never render** โ€” active template's CSS classes don't match any stylesheet rule; ~69 LOC of orphaned dead renderer; docs are the *most* accurate of the 7 (3/9 verified) | + +Atom-tier totals: 6,835 component LOC, 5,560 test LOC (528 tests, 0 skipped), 6,210 story LOC. +Molecule-tier totals: 5,928 / 3,928 / 3,600. Organism-tier totals: ~5,212 / ~3,599 / ~2,415 +(data-grid contributes 0 to the stories figure). Grand total across all three tiers, tests, and +stories: **~44,700 LOC**. + +## Atoms โ€” issues worth a reviewer's attention + +`forge-button` is the only atom that actually backs the "AI-native" marketing claim: a ~170-line +static `AIComponentMetadata` object with per-framework code samples, a11y guidance, and testing +patterns (`button.ts:14-186`). Every other atom uses the thinner `AIMetadata` shape, and four of +them (`alert`, `badge`, `checkbox`, `icon`) never set it at all โ€” `getAIDescription()` on +`forge-checkbox` literally returns `BaseElement`'s generic fallback string despite having a +genuinely detailed `explainState()`. `forge-icon` is the most concerning of the fourteen: it +fetches an arbitrary URL, parses the response as SVG, and injects it via `unsafeHTML` with no +allow-list beyond "is there an `` tag" โ€” a real stored/reflected XSS vector the moment any +caller passes a non-trusted `src`. `forge-select`, the largest and most complex atom (830 LOC, +effectively a full combobox), has a genuine accessibility bug: its `aria-labelledby`/ +`aria-describedby` point at DOM ids that are never rendered anywhere in the template, so the +label/description association is silently broken; it's also the component that reproduced the +project's own self-documented, never-fixed "scheduled an update after completion" Lit performance +warning live during the test run. `forge-skeleton`'s CSS `attr()` custom-property trick was +fact-checked directly (live headless Chrome 142 and Firefox 136 tests) and confirmed +non-functional in any browser version the project targets โ€” but it's dead code, not a live bug, +because a redundant JS path already sets the same value correctly. + +## Molecules โ€” issues worth a reviewer's attention + +The two most serious findings in the whole codebase live here. `forge-form-field` hardcodes three +literal `aria-describedby` IDs (`error-accessible`, `warning-accessible`, `success-accessible`) +into every instance's markup, with a comment admitting it's "for test consistency" โ€” the real, +template-generated IDs are name-interpolated, so this is broken for every field not literally +named `"accessible"` (which happens to be the test fixture's name). `forge-multi-select` builds a +`RegExp` directly from unescaped user search input; typing any regex metacharacter throws an +unhandled `SyntaxError` and breaks rendering โ€” a crash triggerable by normal end-user typing, and +untested. `forge-tooltip`'s `htmlContent` mode binds `.innerHTML=` with zero sanitization โ€” the +second live XSS vector in the library. `forge-date-picker` (the largest molecule at 935 LOC) +claims arrow-key calendar navigation in its AI metadata that simply isn't implemented, and its +calendar popover โ€” despite `role="dialog"` โ€” has no focus trap, unlike `forge-modal`, which has +the best-implemented focus management of any component in the repo. `forge-modal` itself has one +inconsistency: it advertises a `toggle()` action via `getPossibleActions()` that doesn't exist as +a callable method. + +## Organisms โ€” issues worth a reviewer's attention + +`forge-data-grid` is the single largest, most complex file in the repository (1,189 LOC, richest +AI metadata of any organism) and yet is completely absent from `organisms/index.ts`'s barrel +export and has **zero Storybook stories** โ€” the only component in the whole library without one. +Several of its advertised features are stubs: column resize is a literal no-op with a placeholder +comment, and its own locally-defined `VirtualScroller` class is a second, incompatible +implementation of the same windowing logic that `data-table` and `tree-view` already share from +`src/utils/virtual-scroller.ts` โ€” worse, it goes stale after filter/sort because nothing calls +`updateData()` outside of resize events. `forge-data-table` bypasses Lit's declarative rendering +entirely for its header/body โ€” `render()` emits a hardcoded placeholder `` with literal +columns ("ID/Name/Email/Status/Actions") that gets overwritten imperatively via manual DOM +mutation in `updated()`, which risks a visible flash on every render and makes the component's +real behavior invisible to anyone reading `render()`. `forge-tree-view` has a confirmed, +currently-broken visual bug: the live template's BEM-style classes (`tree-node--selected`, +`tree-node--disabled`, etc.) don't match anything in the component's own stylesheet, which was +never updated after a rewrite โ€” so selection highlighting and disabled dimming render as if +unstyled. The biggest cross-cutting finding here isn't a code bug at all: **across all 7 organism +doc pages, only 3 of 43 documented "public methods" actually exist as callable public API**, all +three in `tree-view`. This is systemic enough (every single organism affected) to suggest the docs +were authored aspirationally rather than generated from source โ€” and it directly undermines the +project's AI-tooling pitch, since an AI agent trusting these docs would write code calling +nonexistent methods for the vast majority of organism components. + +## Cross-cutting patterns + +**Inconsistent AI-metadata depth is the through-line of the whole library.** Of 30 components, +only `forge-button` (atom) and `forge-data-grid` (organism) implement the full static metadata +contract the "AI-native" pitch promises; most atoms/molecules use a thinner variant, and 6 of 7 +organisms never set `aiMetadata` at all (only overriding the `aiState` getter), so +`aiState.metadata.purpose` returns `BaseElement`'s literal default `"UI Component"` at runtime for +the majority of organism components. Static `ai-manifest.json`, separately, mis-categorizes every +molecule and organism as `"category": "atom"`, conflates private/internal state fields with +public props (confirmed for `forge-card`: 4 private `@state` fields listed, the real `border` prop +omitted), and fabricates at least one ARIA role (`forge-date-picker` listed as +`role: "combobox"`, which the source never sets). + +**Performance-monitoring code is reimplemented four different, incompatible ways** across the 13 +atom directories: 3 atoms correctly call the inherited `BaseElement.checkPerformance()`; 4 atoms +(`alert`, `badge`, `checkbox`, `icon`) fully reimplement it with shadowed reactive state (this is +also the confirmed root cause of the project's own unresolved "scheduled update after completion" +Lit warning); 2 atoms (`button`, `input`) override it with an incompatible method signature and a +separate parallel tracking object; 5 atoms implement nothing at all, making the inherited +`show-metrics`/`dev-mode` properties silent no-ops. Net effect: identical public API properties, +inherited by all 14 atoms, behave differently depending on which atom you're looking at. A +verbatim ~25-line `.performance-overlay` CSS block is duplicated across 7 files regardless of +which perf-tracking approach each one uses. + +**Dead code is widespread but low-severity individually.** Unused barrel files +(`avatar/index.ts`, `button/index.ts`, `input/index.ts`); slot-presence state tracked via +`slotchange` listeners but never consumed in `render()` (`card`'s 4 fields, `modal`'s +`hasFooter`); AI actions advertised for methods that are private/unreachable or don't exist +(`accordion`'s `expandAll`/`collapseAll`, `modal`'s `toggle`, `card`'s `expand`); a fully orphaned +~69-line duplicate tree renderer in `tree-view.ts` left over from a pre-virtualization +implementation. + +**`data-grid` vs. `data-table` overlap is real but not pure duplication** โ€” the two serve +genuinely different tiers (simple/read-oriented vs. editable/enterprise-grade) and neither is a +strict subset of the other, but they duplicate an entire virtual-scrolling subsystem with +incompatible APIs, and nothing in the docs tells a consumer when to pick one over the other beyond +a single README table row. + +**Two independent, confirmed unsanitized-HTML injection points** exist in the codebase: +`forge-icon`'s remote SVG loader (`icon.ts:400`, `unsafeHTML`) and `forge-tooltip`'s `htmlContent` +mode (`tooltip.ts:516-519`, raw `.innerHTML=`). Both are real if any consuming application ever +passes non-trusted content through them; neither has any test coverage exercising a malicious +payload. + +## Known bugs, ranked by severity + +1. **`forge-icon` SVG XSS** โ€” `unsafeHTML(this.iconData.svg)` from an arbitrary fetched `src` URL, + no sanitization beyond checking for an `` tag (`icon.ts:263-317,400`). +2. **`forge-tooltip` innerHTML XSS** โ€” raw `.innerHTML=${this.content}` bind when + `htmlContent=true`, no sanitization (`tooltip.ts:516-519`). +3. **`forge-multi-select` search crash** โ€” unescaped `RegExp` built from user input throws + `SyntaxError` on any regex metacharacter, breaking rendering (`multi-select.ts:565-574`). +4. **`forge-form-field` broken `aria-describedby` for all real usage** โ€” hardcoded literal IDs + never match rendered elements except in the test fixture (`form-field.ts:378-389`). +5. **Organism docs are 93% fabricated** โ€” 3 of 43 documented public methods actually exist across + all 7 `docs/components/organisms/*.md` pages; would cause AI-tool-generated code to call + nonexistent APIs almost universally. +6. **`forge-tree-view` selected/disabled states unstyled** โ€” live template classes don't match any + CSS rule after an unfinished rewrite; visually broken in the shipped component. +7. **`forge-select` broken label/description ARIA association** โ€” `aria-labelledby`/ + `aria-describedby` reference IDs that don't exist in the template (`select.ts:712-713`). +8. **`forge-data-table` bypasses Lit rendering** โ€” hardcoded placeholder header rendered by + `render()`, then overwritten imperatively in `updated()`; risks a visible flash and hides real + behavior from static reading of the component. +9. **`forge-dropdown` keyboard nav invisible to assistive tech** โ€” DOM focus never moves, no + `aria-activedescendant`; mismatched `combobox`+`menu` ARIA roles. +10. **`forge-data-grid` untested, unbarreled, unstoried** โ€” largest/most complex component in the + repo has zero Storybook coverage and is missing from the organisms barrel export; several + advertised features (column resize, reorder, pinned columns, aggregates, typed cell editors) + are stubs or unwired types. +11. **`forge-date-picker` AI metadata overclaims** โ€” advertises arrow-key navigation that doesn't + exist; its modal-like calendar popover has no focus trap, unlike every other overlay-style + component in the library. +12. **Lit "scheduled update after completion" warning** โ€” self-documented, unresolved in the + project's own TODO doc; confirmed live during the test run for `forge-select`; also affects + `forge-icon`, `forge-checkbox`, `forge-badge` per the project's own notes. +13. **`forge-modal` / `forge-accordion` / `forge-card` fabricated AI actions** โ€” each advertises at + least one action (`toggle`, `expandAll`/`collapseAll`, `expand`) that is either unreachable + (private) or nonexistent. +14. **`ai-manifest.json` staleness and mis-categorization** โ€” every molecule/organism mislabeled + `category: "atom"`; at least one fabricated ARIA role; went stale after `forge-card`'s + `border` prop shipped. +15. **`forge-button` type/CSS mismatch** โ€” `variant="ghost"|"link"` compiles but has no CSS; + `PerformanceMode` type differs from the actual runtime property type. +16. **`forge-skeleton` dead CSS `attr()` rule** โ€” confirmed non-functional by live browser test; + zero user impact because a JS path already overrides it correctly. Lowest-severity item on + this list, included for completeness/fact-check provenance. + +## Recommendations + +**If reviving the project:** treat this less as "fix bugs" and more as "close the gap between +marketing and reality" โ€” the codebase is structurally sound (100% test coverage by file, +consistent `BaseElement` inheritance, real and mostly-correct ARIA patterns in the stronger +components like `modal`, `multi-select`, `progress`) but the AI-native/documentation layer was +clearly built faster than it was verified. Priority order: (1) patch the two XSS vectors and the +multi-select crash โ€” these are exploitable today with zero configuration changes; (2) regenerate +or hand-fix the organism docs from source rather than trust the existing "Public Methods" tables, +given the 3/43 verification rate; (3) either implement or delete `data-grid`'s stub features and +get it into the barrel/Storybook before shipping it as a "production" component; (4) pick one +performance-monitoring implementation and retrofit all 14 atoms to use it, closing the project's +own long-open Lit warning TODO in the process; (5) decide whether `ai-manifest.json` generation +should introspect actual component state (accurate but harder) or stay hand-authored boilerplate +(cheap but currently actively misleading) โ€” right now it's neither reliable enough to trust nor +cheap enough to ignore. + +**If not reviving the project:** the atoms tier (14 components, full test/story coverage, +`forge-button`'s metadata as a template) is the most reusable/extractable subset if any individual +components get salvaged elsewhere; `forge-modal`'s focus-trap implementation and +`forge-multi-select`'s live-region announcer are the two standout a11y implementations worth +lifting into a future component library regardless of what happens to the rest of Forge. diff --git a/plans/analysis-2026-07/04-testing-build-cicd.md b/plans/analysis-2026-07/04-testing-build-cicd.md new file mode 100644 index 0000000..2eff291 --- /dev/null +++ b/plans/analysis-2026-07/04-testing-build-cicd.md @@ -0,0 +1,457 @@ +# @nexcraft/forge โ€” Testing, Build & Packaging, CI/CD, and Toolchain-Today Verdict + +Repo: `/home/air_buster/rollg/ignis/apps/forge` ยท v0.10.0 ยท branch `develop` @ `73f3b59` (2025-10-15) ยท +`origin/develop` is actually 4 commits ahead at `85238d0`; `origin/main` is at `164a357` (2025-11-11, +a Dependabot auto-merge โ€” the true last activity on the project). Analysis date: 2026-07-13. + +## TL;DR + +The toolchain itself is in good shape: type-check, lint, the full unit-test suite, and the core +build all pass cleanly today, nine months untouched, with zero code changes required. That is the +good news, and it's a genuine, verifiable positive signal for reviving the project. + +Everything the README uses to sell the library, however, is materially overstated or broken. +Coverage is 85.5%, not the 86.4%/87.2%/90%+ claimed in three different places in the same README. +The flagship "AI-native" export/validation subsystem (1,295 lines) is quietly excluded from the +coverage metric and has zero tests. The "under 10KB, tree-shakeable" bundle claim is off by roughly +40-90x โ€” the real bundle is 467KB raw / 91KB gzip โ€” and the entire "selective imports" feature (29 +of ~38 export map entries) doesn't just fail to deliver savings, it throws a runtime error under any +bundler that honors the package's own `sideEffects: false` declaration. CI/CD has one workflow +(`auto-label.yml`) that has failed 16/16 times since introduction due to a YAML syntax error, two +competing and partially-broken beta-release mechanisms, a stale `publish-packages` script that would +silently under-publish if anyone ran it, and a GitHub Pages deployment pointing at a dead domain. +`npm audit` reports 4 critical / 16 high / 6 moderate vulnerabilities, though the criticals are +dev-only tooling (vitest) not shipped to consumers. + +None of this is a "the codebase is rotten" story โ€” it's a "the marketing and the packaging drifted +away from the engineering, and nobody was watching CI for the last eight months" story. The +underlying component code, tests, and build pipeline are sound; the public-facing promises about +that code are not. + +--- + +## 1. Testing + +### 1.1 Real coverage vs. the README badge + +The README's coverage badge reads **86.4%** (`README.md:5`). It is contradicted twice more in the +same file โ€” "Overall Test Coverage: 87.2%" (`README.md:435`) and a table entry claiming 87.2% +"ACHIEVED" against an ">85%" target (`README.md:507`). None of these three numbers match what's +actually on disk. + +The real, locally-generated coverage report (`coverage/index.html`, gitignored, timestamped +2025-10-04 โ€” 11 days before the repo's last commit, so even this snapshot is slightly stale) +measures: + +| Metric | Measured | README claims | +|---|---|---| +| Statements | 85.52% (8718/10193) | 86.4% (badge) / 87.2% (body, x2) | +| Branches | 84.56% (2132/2521) | โ€” | +| Functions | 86.66% (650/750) | โ€” | +| Lines | 85.52% (8718/10193) | 90%+ (`README.md:463`) | + +The coverage config's own enforced threshold is only **70%** for branches/functions/lines/statements +(`vitest.config.ts`) โ€” well below the ~85% actually achieved, so the gate wouldn't catch a +regression until coverage dropped roughly 15 points. + +**Coverage by area** (statements %, from `coverage/index.html`): + +| Area | Coverage | Note | +|---|---|---| +| `components/atoms/skeleton` | 100% | highest | +| `core` | 93.79% | | +| several molecules | >92% | | +| `components/atoms/icon` | 65.02% | lowest atom | +| `components/organisms/data-table` | 65.24% (functions 73.8%) | lowest organism | +| `components/organisms/data-grid` | 68.42% (functions **52.27%**) | weakest function coverage anywhere | +| `components/organisms/tree-view` | 72.26% | | +| `components/organisms/tabs` | 78.52% | | +| `components/atoms/checkbox` / `badge` | ~76% each | | +| `ai-metadata-exporter.ts` / `ai-metadata-validator.ts` | **not measured (excluded)** | see 1.2 | + +The README's own per-component coverage table (`README.md:418-431`) is stale for a third of its +rows โ€” Icon, Alert, Checkbox, and Badge are overstated by 13 to 24 percentage points versus the +current measured values (e.g. Badge claimed 100%, actually 75.92%). Input, Switch, RadioGroup, and +Skeleton match exactly, suggesting the table was accurate once and simply never regenerated. + +### 1.2 The most consequential finding in this section: the AI export/validation subsystem is untested and hidden from the metric + +`vitest.config.ts`'s coverage `exclude` list carves out `src/core/ai-metadata-exporter.ts` (734 +lines) and `src/core/ai-metadata-validator.ts` (561 lines) โ€” 1,295 lines total, with **zero test +files anywhere**. This exclusion was added silently in commit `9e8c88b` ("fix(test): resolve +coverage threshold failures by fixing configuration", 2025-09-29); the commit message justifies +excluding `packages/**` and `src/index.ts` but says nothing about these two files. This is the code +underpinning the library's flagship "AI training dataset export" and "AI metadata quality +validation" system โ€” the core of its "AI-native" positioning โ€” and it is both untested and +deliberately removed from the metric used to justify the coverage badge. + +By contrast, per-component AI methods are genuinely well tested: `getPossibleActions()` appears in +26/30 component test files, `explainState()` in 25/30, `.aiState` assertions in 19/30, with +meaningful field-level checks (not just existence checks). The gap is specifically the +export/validation layer, not the per-component AI surface. + +### 1.3 test:unit / test:a11y split โ€” fragile, but not broken today + +``` +"test:unit": "vitest run -t \"^((?!WCAG|Accessibility Compliance).)*$\"", +"test:a11y": "vitest run -t \"WCAG|Accessibility Compliance\" --pool=forks --poolOptions.forks.singleFork=true" +``` + +The split is a pure Vitest `-t` name-regex filter against the full `describe`+`it` string โ€” no +dedicated config, project, or file-naming convention. Verified by actually running both: +`test:unit` โ†’ 36 files, 1147 passed, 35 skipped (of 1182), 22.2s; `test:a11y` โ†’ 6 files matched +(all organism-tier: data-grid, tree-view, navigation-bar, pagination, accordion, tabs), 35 passed, +5.7s. + +This is fragile in a way that hasn't yet caused a problem but easily could: + +- Only 6 of 30 component test files match the `test:a11y` regex โ€” zero atoms, zero molecules. 18 + other files *do* have accessibility-focused blocks, just named `describe('Accessibility', ...)` + (singular, no "Compliance") โ€” invisible to the regex, so those tests silently run under + `test:unit` instead. Functionally harmless (everything still runs under `npm test`) but means + `npm run test:a11y` alone is not a meaningful "run all accessibility tests" command โ€” it only + captures the 5 real axe-core scans (`.to.be.accessible()`, used in tabs, navigation-bar, + accordion, pagination, tree-view). +- The whole mechanism depends on developers remembering an exact string ("WCAG" or "Accessibility + Compliance," not "Accessibility" or "ARIA"), with no lint rule or CI check enforcing it. A rename + silently reshuffles which bucket a test lands in. +- `test:coverage` runs `test:unit -- --coverage && test:a11y` โ€” no `--coverage` on the second + invocation, so whatever branches the 35 a11y-named tests uniquely exercise are invisible to the + coverage numbers reported to CI/PRs. + +### 1.4 Test quality spot-checks + +The majority pattern is genuine behavior testing, not smoke tests: `button.test.ts` exercises real +DOM clicks, event-suppression on disabled/loading states, CSS class application, and a substantial +AI-methods block that calls `getPossibleActions()`/`explainState()` and asserts on structured +returned data with specific substrings. + +Two categories of real quality problems were found, both narrow but worth knowing about before +trusting the suite as a safety net for a rewrite: + +- **Tautological tests.** `button.test.ts:19-21` is a literal `expect(true).to.be.true` that tests + nothing. `toast.test.ts:204-229` has two tests that only assert "no exception was thrown" for + hover-pause and mouse interaction, explicitly commented as unable to test the real behavior. +- **Tests that duplicate rather than exercise production logic.** `icon.test.ts:138-184` sets a + private field, then re-implements the exact performance-degradation `if` condition from + `icon.ts` inline in the test itself, rather than triggering the real code path โ€” meaning a + regression in the actual render-timing logic would not be caught. Confirmed identical in **4 + files** (`icon.test.ts`, `badge.test.ts`, `switch.test.ts`, `checkbox.test.ts`), all in their + "Performance Monitoring" blocks, likely because happy-dom renders are sub-millisecond and nobody + mocked `performance.now()`. + +**Flakiness risk:** real (non-fake) timers drive async assertions in `data-grid.test.ts` (6ร— +`setTimeout(..., 350)`, โ‰ฅ2.1s of real wait) and `performance-dashboard.test.ts` (7ร— +`setTimeout(..., 150)`, โ‰ฅ1.05s) โ€” a documented historical flakiness source (commit `8537b73`: +"data-grid timeouts, WCAG tests with Axe race conditions"). Three other files use +`vi.useFakeTimers()` correctly, so the codebase knows the right pattern but applies it +inconsistently. + +### 1.5 Untested components / packages + +At the component level there is no gap: all 29 component source files under +`src/components/{atoms,molecules,organisms}` have a corresponding test file (100% file-level +coverage). The real gap is structural and much larger: + +**All 6 npm workspace packages have zero test files** โ€” `forge-angular`, `forge-mcp-figma`, +`forge-react`, `forge-rhf`, `forge-tokens`, `forge-vue`. These are separately published to npm with +no automated tests whatsoever for the React hooks, Vue composables, Angular directives, +react-hook-form integration, token generation, or the Figma MCP server. The root `vitest.config.ts` +never scans `packages/**`, so this isn't visible in any coverage number. + +Two smaller items: `test-performance.js` is a dead, unintegrated performance-check script (not in +any npm script or CI workflow โ€” the only place it's referenced is an exclusion in the coverage +config); and the README documents three test commands that don't exist in `package.json` +(`test:e2e`, `test:visual`, `test:all`) plus a "Visual regression (Chromatic)" claim that's aspirational +(only a Storybook addon is registered, no token, no CI job). + +--- + +## 2. Build & Packaging + +### 2.1 Exports map integrity + +Walking every entry in `package.json`'s `exports` map against the filesystem: the core entries +(`.`, `./tokens.css`, `./plugin`, `./custom-elements.json`, `./ai-manifest.json`, +`./ai-index.json`) and all 29 component subpaths (`./button`, `./modal`, `./data-grid`, etc.) +resolve to real files. Two entries do not: + +- **`./types/framework-integration` โ†’ `./dist/types/framework-integration.d.ts` does not exist.** + `scripts/cleanup-types.js` unconditionally deletes `dist/types` after the `.d.ts` bundling step, + but the exports map still points a subpath at a file inside that now-deleted directory. Any + consumer importing this type errors with `TS2307: Cannot find module`. +- **`./ai-tools/* โ†’ ./ai-tools/*` โ€” the directory doesn't exist anywhere in the repo.** It was + deliberately deleted (commit `cc3f367`, "remove incomplete ai-tools/ folder ... Redundant with + existing AI metadata systems"), but the `package.json` `files`/`exports` entries were never + cleaned up, and `scripts/generate-ai-index.js` still writes `functionCalling: './ai-tools/'` into + the published `ai-index.json` โ€” the machine-readable metadata this library ships specifically + for AI tooling consumption points at a path that was intentionally deleted nine months earlier. + +Both were confirmed present in the exact broken form in the real published npm tarball for +`@nexcraft/forge@0.10.0` (byte-identical to the local `dist/`, per ยง2.2), so these are live issues +for anyone installing the package today, not local artifacts. + +### 2.2 Actual bundle sizes vs. the <10KB claim + +The README asserts `<10KB` bundle size in three places: the top badge (linking to bundlephobia), +`README.md:360` ("๐Ÿ“ฆ Optimized Bundle | <10KB per component"), and `README.md:508` ("Bundle Size +(per component) | <10KB | <10KB | โœ… ACHIEVED"). Measured reality: + +| Artifact | Raw | Gzip | vs. <10KB claim | +|---|---|---|---| +| `dist/nexcraft-forge.es.js` (main ESM) | 467,403 B (~467KB) | 91,239 B (~91KB) | ~46x / ~9x over | +| `dist/nexcraft-forge.umd.js` (main UMD) | 409,307 B (~409KB) | 84,362 B (~82KB) | ~41x / ~8x over | +| `dist/exports/button.js` (per-component shim) | 796 B | 426 B | technically under, but see below | +| `dist/exports/data-table.js` | 832 B | 435 B | " | +| `dist/exports/tree-view.js` | 821 B | 433 B | " | + +The per-component shim files are individually tiny, but every one of them does a bare +`import '../nexcraft-forge.es.js'` โ€” a side-effect-only import with zero bound specifiers โ€” which +pulls in and evaluates the *entire* 467KB/91KB-gzip main bundle before extracting one class off the +global custom-element registry. So the effective cost of `import { ForgeButton } from +'@nexcraft/forge/button'` is not ~800 bytes, it's the full 91KB gzip, identical to importing +everything. This was verified byte-for-byte against the real npm registry tarball +(`@nexcraft/forge-0.10.0.tgz`) โ€” not a stale local artifact. + +### 2.3 sideEffects:false vs. custom-element registration โ€” the tree-shaking claim is broken, empirically + +`package.json:171` declares `"sideEffects": false` as a flat boolean (package-wide, no per-file +exceptions). This tells any conforming bundler it may drop any import whose bindings appear +unused. But every component self-registers via Lit's `@customElement` decorator +(`src/components/atoms/button/button.ts:11`, and 29 more like it), which compiles to an +unconditional, synchronous `customElements.define(tag, Class)` call at module-evaluation time โ€” a +genuine, irreversible, application-wide side effect that the `sideEffects: false` declaration +explicitly denies exists. + +This was reproduced empirically with esbuild (the engine Vite uses for pre-bundling, and one of the +most common production bundlers): bundling an entry that imports `{ ForgeButton }` from +`dist/exports/button.js` with tree-shaking enabled produces the warning `Ignoring this import +because ".../nexcraft-forge.es.js" was marked as having no side effects [ignored-bare-import] ... +"sideEffects" is false in the enclosing "package.json" file: package.json:171`, and strips the +side-effect import out entirely. The resulting bundle **unconditionally throws** `"ForgeButton not +found. Make sure @nexcraft/forge is properly loaded."` at import time. This affects all 29 +per-component subpath exports โ€” the entire "selective imports" feature the docs advertise with +numbers like "~15KB per component" and "85% reduction" (`docs/guides/selective-imports.md`, +`CHANGELOG.md`). Webpack 5's production `optimization.usedExports` + `sideEffects` handling and +Vite/Rollup's `moduleSideEffects` resolution both derive from the same package.json field, so this +is not an esbuild-specific quirk. + +Notably, the project's own ADR anticipated exactly this problem and specified the correct fix โ€” a +scoped `sideEffects` array plus a dedicated `define.js` registration file per component +(`plans/adrs/ADR-011-package-distribution.md:121-124`) โ€” but that design was never carried into the +shipped `package.json`. The fix is either scoping `sideEffects` to the files that actually register +elements, or redesigning the export shims per the ADR's original plan. + +No demo app in `demos/` actually exercises the selective-import path (only `dist/tokens.css` and +JSON metadata files are imported by path), which is consistent with this bug going unnoticed for +nine months โ€” the one thing that would have caught it was never wired up. + +### 2.4 dts pipeline + +The type-declaration bundling pipeline itself works correctly: `tsc --emitDeclarationOnly` โ†’ +`rollup -c rollup.dts.config.js` (via `rollup-plugin-dts`) โ†’ `dist/index.d.ts` (89KB), a +well-formed single-file aggregation of all component/prop/event/AI-metadata types. No defects found +in this part. + +One cleanup gap: `dist/utils/` ships 14 orphaned `.d.ts` files with **no matching `.js` files** and +**no exports-map entry**, because `cleanup-types.js`'s deletion list (`components`, `core`, `test`, +`types`) never includes `utils`. ~24KB of dead, unreachable type-only cruft shipped in every +install (confirmed in the real npm tarball). Low severity โ€” bloat, not breakage. + +Two other packaging issues: `lit` is declared as both a `dependency` and a `peerDependency`, but the +build bundles its own copy anyway (`rollupOptions.external: []`) โ€” the peerDependency declaration is +functionally inert, and any consumer who also imports `lit` directly ends up with two Lit instances +on the page. And `./plugin` (the Tailwind plugin subpath) imports `tailwindcss/plugin` at runtime, +but `tailwindcss` is only in `devDependencies` โ€” a consumer using `@nexcraft/forge/plugin` without +independently installing Tailwind gets `Cannot find module` at build/config-load time. + +--- + +## 3. CI/CD & Release + +### 3.1 Workflow map (7 workflows) + +| Workflow | Trigger | Purpose | +|---|---|---| +| `ci.yml` | push/PR to `main`, manual | Gate: changeset-check, lint, typecheck, test:coverage, security-audit (blocking), build | +| `develop.yml` | push/PR to `develop`, manual (+publish input) | Same gates scoped to `develop`, plus the **real** changesets-based beta publish path | +| `release.yml` | on `ci.yml` completing (branch `main`) | Security gate โ†’ `changesets/action` โ†’ `npx changeset publish` (the actual production release mechanism) โ†’ sync-develop โ†’ update-examples | +| `beta-release.yml` | manual dispatch only, any branch | Competing, hand-rolled beta release (no changesets) โ€” publishes main package + (buggy) forge-rhf only | +| `deploy.yml` | on `release.yml`/Release workflow completing, push to `demos/**`/`docs/**`, manual | Builds Storybook + Next.js demo, deploys to GitHub Pages | +| `auto-label.yml` | PR opened/synchronize/reopened/ready_for_review/converted_to_draft | PR labeling by path/size/WIP-status/title โ€” **100% broken, see 3.2** | +| `security-audit-nightly.yml` | daily 02:00 UTC, manual | `npm audit` wrapper โ†’ Discord webhook, non-blocking (`--no-fail`) | + +### 3.2 auto-label.yml โ€” confirmed 100%-failing since introduction + +`.github/workflows/auto-label.yml` lines 44 and 50 contain an unquoted YAML scalar with an internal +unescaped colon (`--add-label "status: wip"` inside a plain `run:` value) โ€” invalid YAML. +Independently confirmed two ways: `python3 -c "import yaml; yaml.safe_load(...)"` fails with +`mapping values are not allowed here` at line 44, and live GitHub Actions history +(`gh run list --workflow=auto-label.yml`) shows **16 out of 16 recorded runs failed**, every one +with `0s` duration and `jobs: []` โ€” GitHub's diagnostic for an unparseable workflow file. This +automation, introduced in commit `3c5dffe` on 2025-10-15, has never labeled a single PR in its +entire existence, despite a fully-written `.github/labeler.yml` config sitting ready to use. Fix is +a one-line quoting change per occurrence. + +### 3.3 End-to-end release path โ€” what actually happens + +A PR merges to `main` (mostly Dependabot auto-merges since Nov 2025) โ†’ `ci.yml` runs on the push, +but **only the `smoke-test` job** (`npm audit`, `npm run build`, `npm run validate:ai`) โ€” +`lint`/`typecheck`/`test`/`build` are all `if: github.event_name == 'pull_request'` and skip on +plain pushes โ†’ `release.yml` fires on `ci.yml` completing: security-audit gate (blocking on +critical vulns) โ†’ downloads the CI build artifact or rebuilds if missing (this fallback always +triggers in practice, since push-triggered CI never produces the artifact release.yml looks for) โ†’ +explicitly rebuilds `forge-react`/`forge-vue`/`forge-angular`/`forge-rhf` โ†’ `changesets/action` runs +`npx changeset version` + `npx changeset publish`, which publishes **every non-private workspace +package with a pending changeset** โ€” the real mechanism, and it does correctly publish all 7 +targets together (confirmed via matching npm registry timestamps to the automated release-PR +commits). + +### 3.4 Which packages actually publish โ€” and the stale script that would mislead you + +Root `package.json`'s `publish-packages` script only lists 4 targets: root, `forge-rhf`, +`forge-tokens`, `forge-mcp-figma` โ€” **it never mentions `forge-react`, `forge-vue`, or +`forge-angular`**. This script is never invoked by any workflow, hook, or CI step +(`grep -rn "publish-packages"` finds only its own definition). Yet all 7 packages (root + all 6 +workspace packages) genuinely are live and current on the npm registry, published via the +changesets mechanism in `release.yml`, not this script: + +| Package | Latest on npm | Last publish | +|---|---|---| +| `@nexcraft/forge` | 0.10.0 | 2025-10-08 | +| `@nexcraft/forge-react` | 1.0.5 | 2025-10-08 | +| `@nexcraft/forge-vue` | 1.0.2 | 2025-10-08 | +| `@nexcraft/forge-angular` | 1.0.2 | 2025-10-08 | +| `@nexcraft/forge-rhf` | 1.0.2 | 2025-10-08 | +| `@nexcraft/forge-tokens` | 0.2.0 | 2025-10-02 | +| `@nexcraft/forge-mcp-figma` | 0.2.0 | 2025-10-02 | + +`publish-packages` is therefore dead/orphaned documentation-as-code: anyone reading `package.json` +scripts to understand "how do I publish this" would run it and silently under-publish 3 of 7 +packages. + +`beta-release.yml` compounds this with its own bug: its "smart publishing" check for whether +`forge-rhf` needs publishing (`git diff --quiet HEAD~1 packages/forge-rhf/`) always evaluates true, +because the immediately preceding commit always touches `forge-rhf/package.json` (an unconditional +version bump two steps earlier in the same workflow) โ€” so forge-rhf publishes on every single beta +run regardless of whether it changed, exactly contradicting the stated intent of the commit that +added this logic. The other 4 workspace packages have no publish steps in this workflow at all. +`develop.yml`'s changesets-based `publish` job is the only complete/correct beta mechanism; these +two beta paths can drift out of sync with each other. + +### 3.5 Other stale/broken workflow findings + +- **No branch protection on `main`** (`404 "Branch not protected"` from the GitHub API) โ€” no + required checks, no required review, direct pushes allowed (consistent with `release.yml`'s own + jobs pushing straight to `main`/`develop`). +- **Deployed site is unreachable.** `deploy.yml` reports success, but the configured custom domain + `forge.ignis.dev` doesn't resolve (`NXDOMAIN`); the GitHub Pages URL 301-redirects into that dead + domain. The `gh-pages` branch is a stale relic from before the modern Pages-via-Actions method, + last touched 2025-09-08. +- **`PAT_TOKEN` fallback masks a missing secret** โ€” `sync-develop` uses `secrets.PAT_TOKEN || + secrets.GITHUB_TOKEN`; `PAT_TOKEN` doesn't exist, so it silently always falls back. Not currently + broken, but shows an intended setup step was never completed. +- **No CI coverage for `forge-vue`/`forge-angular`** โ€” `ci.yml`'s `typecheck` job only builds + `forge-react`; the other two are first compiled anywhere in the pipeline inside `release.yml`, + after CI has already gone green and a release is about to publish. +- **No workspace package's own tests run anywhere** โ€” `ci.yml`'s `test` job only invokes the root + `vitest.config.ts` (`src/**`); `forge-rhf` has its own `test` script but nothing ever calls it. +- **Lint scope is narrow** โ€” root `lint` covers only `src/**` and `forge-rhf`; the other 5 workspace + packages have no lint script and are never linted. +- **No `actionlint`/`yamllint` anywhere** in CI or the pre-commit hook โ€” the root-cause enabler for + `auto-label.yml`'s bug surviving undetected for nine months (prettier round-trips the YAML fine + without validating GitHub-Actions semantics). + +### 3.6 CI health signal / dormancy state + +`origin/main`'s true last commit is 2025-11-11 (a Dependabot auto-merge). Since then: **10 open +Dependabot PRs** (oldest ~7.5 months old), zero human commits, zero non-Dependabot PRs. The only +workflow that has run reliably every day through the dormant period is `security-audit-nightly.yml` +(145+ consecutive successful runs) โ€” but "success" here just means the non-blocking `--no-fail` +script completed, not that it found nothing (ยง4). A batch of Dependabot major-version-bump PRs from +2025-11-24 (storybook 9โ†’10, vitest 3โ†’4) already fail Lint/TypeCheck/Test/SecurityAudit and remain +open โ€” concrete evidence the toolchain has started bit-rotting against newer majors of its own +dependencies, even though the pinned-lockfile toolchain still works fine today (ยง4). + +--- + +## 4. Toolchain-today verdict (2026-07-13, this checkout, read-only, `node_modules` already installed) + +| Step | Command | Result | +|---|---|---| +| Type-check | `npm run type-check:local` (`tsc --noEmit`) | **PASS** โ€” exit 0, zero errors | +| Lint | `npm run lint:local` (`eslint src/**/*.ts`) | **PASS** โ€” exit 0, zero warnings/errors (scope: `src/**` only, not workspace packages) | +| Unit tests | `npm run test:unit` | **PASS** โ€” 36/36 test files, 1147 passed / 35 skipped (1182 total), 19.4s | +| Build | `npm run build:core` | **PASS** โ€” vite build (68 modules, 1.05s), `build:types`, `bundle:types`, `cleanup:types`, `build:exports` all succeeded; output matches ยง2 sizes exactly (467.40 KB / 91.38 KB gzip) | +| `git status` | before and after all steps | **clean**, no stray artifacts (`dist/` is gitignored) | + +Zero code changes were required to get a fully green local toolchain run nine months after the last +commit โ€” a genuinely positive signal for anyone considering reviving this project. The only rot is +at the dependency-security layer. + +### npm audit severity breakdown + +`npm audit --json`: **26 total** (0 info, 0 low, 6 moderate, 16 high, 4 critical), across 49 prod / +624 dev / 18 optional / 19 peer dependencies (678 total). + +| Severity | Count | Packages | +|---|---|---| +| Critical | 4 | `vitest`, `@vitest/browser`, `@vitest/coverage-v8`, `@vitest/ui` | +| High | 16 | `@angular/common`, `@angular/core`, `@angular/forms`, `@angular/platform-browser`, `@isaacs/brace-expansion`, `flatted`, `glob`, `happy-dom`, `koa`, `minimatch`, `picomatch`, `playwright`, `rollup`, `storybook`, `vite`, `ws` | +| Moderate | 6 | `ajv`, `brace-expansion`, `js-yaml`, `postcss`, `qs`, `yaml` | + +The 4 criticals are concentrated entirely in the vitest toolchain: `vitest` (GHSA-5xrq-8626-4rwp, +CVSS 9.8, arbitrary file read/execute when the Vitest UI server is listening โ€” installed version +3.2.4 confirmed in the vulnerable `<3.2.6` range) and `@vitest/browser` (GHSA-g8mr-85jm-7xhm, CVSS +9.8, RCE via CDP proxy/config overwrite when Browser Mode is exposed). Both require the vitest +dev/UI/browser server to actually be running and reachable โ€” running `npm run test:unit` (a plain +`vitest run`, as done here) does not trigger these conditions. All 4 criticals and most of the highs +are **devDependencies only** โ€” not shipped in the published `@nexcraft/forge` npm package โ€” but they +are real risk for anyone running `vitest --ui` locally against this lockfile, and the Angular/ +Playwright/Storybook highs are relevant to anyone building the `forge-angular` workspace package or +running the demo/Storybook tooling. `npm audit fix` / manual bumps have not been applied since +around the October 2025 freeze. + +--- + +## Ranked risks + +1. **Bundle-size/tree-shaking claims are false, and "selective imports" actively throws in + production** under any bundler that honors `sideEffects: false` (esbuild, Vite prod, Webpack 5 + default settings) โ€” the single most damaging finding for existing consumers. (ยง2.2, ยง2.3) +2. **The AI export/validation subsystem โ€” core of the "AI-native" pitch โ€” has zero tests and is + deliberately excluded from the coverage metric used to justify marketing claims.** (ยง1.2) +3. **`auto-label.yml` has been 100% broken since introduction (16/16 failed runs), uncaught for 9 + months**, symptomatic of no `actionlint`/`yamllint` anywhere in CI or hooks. (ยง3.2, ยง3.5) +4. **Two competing beta-release mechanisms, a stale `publish-packages` script that would + silently under-publish 3 of 7 packages, and a no-op "smart publish" check in `beta-release.yml`** + โ€” real risk of package-version drift for a new maintainer. (ยง3.4) +5. **10 open Dependabot PRs, some already failing CI (major version bumps)** โ€” the "toolchain works + today" verdict (ยง4) reflects the frozen Oct 2025 lockfile, not what happens the moment + dependencies move. (ยง3.6) +6. **4 critical / 16 high npm audit findings**, dev-tooling-scoped but unaddressed for 9 months. (ยง4) +7. **README numeric claims (coverage, component count, bundle size, Chromatic, three non-existent + test scripts) are stale/aspirational across the board** โ€” individually low severity, but + collectively mean nothing in the README's stats can be trusted without re-verification. (ยง1.1, ยง1.5, ยง2.2) +8. **Two broken exports-map entries and ~24KB of orphaned `.d.ts`-only cruft** โ€” low severity, easy + fixes. (ยง2.1, ยง2.4) +9. **GitHub Pages resolves to a dead custom domain; `main` has no branch protection.** Cosmetic but + visible if anyone follows the docs-site link today. (ยง3.5) + +## Recommendations + +- **Fix the `sideEffects` scoping before any revival announcement** โ€” either the ADR-011 array + approach with a per-component `define.js`, or drop "selective imports" and be honest the main + bundle is ~91KB gzip. This is a live bug affecting real installs today. +- **Correct or remove every unverified README claim** (coverage/bundle-size badges, component + count, Chromatic checkmark, three non-existent `test:*` scripts) before using the README to pitch + continued investment. +- **Add tests for `ai-metadata-exporter.ts`/`ai-metadata-validator.ts`** and drop their coverage + exclusion โ€” either the feature matters (test it) or it doesn't (remove it). +- **Fix `auto-label.yml`'s one-line YAML bug** and add `actionlint` to CI/pre-commit so the next + workflow-syntax error doesn't go 9 months unnoticed. +- **Consolidate to one beta-release mechanism** (`develop.yml`'s changesets path is correct) and + delete or fix `beta-release.yml` plus the stale `publish-packages` script, then reconcile the + Dependabot backlog โ€” several are major-version bumps needing real compatibility fixes, not just merges. +- **Point or remove the dead `forge.ignis.dev` domain** and enable basic branch protection on `main` + now that no one is watching direct pushes. diff --git a/plans/analysis-2026-07/05-packages-and-ecosystem.md b/plans/analysis-2026-07/05-packages-and-ecosystem.md new file mode 100644 index 0000000..3785079 --- /dev/null +++ b/plans/analysis-2026-07/05-packages-and-ecosystem.md @@ -0,0 +1,353 @@ +# Packages & Ecosystem โ€” @nexcraft/forge Due-Diligence + +Repo: `/home/air_buster/rollg/ignis/apps/forge` (`@nexcraft/forge` v0.10.0, npm workspaces: +`packages/{forge-react,forge-vue,forge-angular,forge-rhf,forge-tokens,forge-mcp-figma}` + +`demos/{nextjs-app,vue-app,vanilla-app}`). GitHub: `dev-ignis/forge`. Last commit 2025-10-15 +(`develop`) / 2025-11-11 (`main`). Analysis date: 2026-07-13 โ€” **9 months dormant**. + +## TL;DR + +This is a solo-built, AI-assisted "sprint and abandon" project: one human author (`ignis`, +`maildevcom+1@gmail.com`) plus heavy bot automation produced 700 commits and 60 published +`@nexcraft/forge` versions in ~6 weeks (Aug 28 โ€“ Oct 8, 2025), then the entire six-package +ecosystem froze simultaneously. The core library and its React wrapper are genuinely solid +engineering; everything downstream of that โ€” Vue/Angular wrappers, the RHF adapter, the tokens +CLI, and especially the "MCP server" โ€” ranges from lightly-tested to non-functional. The +headline finding is that **`@nexcraft/forge-mcp-figma`, published to npm and advertised as a +working MCP server, has never implemented the Model Context Protocol handshake at any point in +its history** โ€” any real MCP client fails on the first message. Ownership is a hard bus-factor-of-1: +the same individual controls the GitHub repo (personal `User`, not an org), the npm account +(`rollg`, single maintainer on all six packages), and the sole `NPM_TOKEN` CI secret, with no +provenance/OIDC attestation on the stable release path. 99 commits sit unreleased on `develop`, +including a security fix (Vite/esbuild CVE) that never reached npm. Reviving this project is +feasible โ€” the core is not rotten โ€” but it requires deciding what to do with the two clearly-weak +links (forge-mcp-figma, forge-tokens) before presenting this as a serious multi-framework library +to new consumers. + +--- + +## 1. The six workspace packages + +### 1.1 State table + +| Package | Local version | npm `latest` | Published | Downloads/moยน | Wrapper coverage | Verdict | +|---|---|---|---|---|---|---| +| `@nexcraft/forge` (core) | 0.10.0 | 0.10.0 | 2025-10-08 | 138 | โ€” | **alive-but-frozen** | +| `@nexcraft/forge-react` | 1.0.5 | 1.0.5 | 2025-10-08 | 57 | 29/29 components (100%, per-component, typed) | **stale, most mature** | +| `@nexcraft/forge-vue` | 1.0.2 | 1.0.2 | 2025-10-08 | 41 | 100% by construction (generic composables, no typed bindings) | **stale, weak CI** | +| `@nexcraft/forge-angular` | 1.0.2 | 1.0.2 | 2025-10-08 | 45 | 100% by construction (generic directives, no typed bindings) | **stale, weak CI** | +| `@nexcraft/forge-rhf` | 1.0.2 | 1.0.2 | 2025-10-08 | 57 | 4 field adapters + factory | **stale-but-usable** | +| `@nexcraft/forge-tokens` | 0.2.0 | 0.2.0 | 2025-10-02 | 47 | Figma Variables CLI | **stale-but-usable** | +| `@nexcraft/forge-mcp-figma` | 0.2.0 | 0.2.0 | 2025-10-02 | 23 | 3 custom RPC methods | **broken** | + +ยน npm downloads, window 2026-06-12 โ†’ 2026-07-11. Every published version's `dist-tags.latest` +exactly matches what's checked into the repo โ€” there is no pending unshipped version bump; the +gap between disk and npm is entirely unreleased *feature* work on `develop` (ยง4.3), not a missed +publish. + +All six packages published within the same two release windows (Oct 8 for +react/vue/angular/rhf/core; Oct 2 for tokens/mcp-figma) and nothing has shipped since โ€” the +ecosystem froze as a unit, not gradually. + +### 1.2 The `workspace:*` question + +Root `package.json` carries `"@nexcraft/forge-react": "workspace:*"` as a devDependency โ€” this is +Yarn/pnpm workspace-protocol syntax that npm's docs do not officially support. **Verified this does +not block a fresh `npm install`**: both a dry-run against the real repo and an isolated from-scratch +sandbox test succeeded (npm 10.9.2). npm's arborist workspace-linker matches the dependency name to +a local workspace package and symlinks it regardless of the version-range string being +non-standard; this is empirically reliable but undocumented behavior, not a guaranteed contract. + +It exists for a narrow reason, not general workspace linking style: root itself never imports +`@nexcraft/forge-react` (the only repo hit is a `console.log` string literal in +`vite.config.ts:92`). The line was added in commit `c348b62` purely so npm's hoisting makes +`forge-react`'s types resolvable for `forge-rhf`'s `tsc` step in CI. **Recommendation**: replace it +with a plain `"*"` or `"file:packages/forge-react"` โ€” npm workspace auto-linking works with either, +without relying on syntax npm's own documentation doesn't endorse. + +### 1.3 Drift between core and wrappers + +The three framework wrappers are architecturally split into two different strategies: + +- **forge-react** is 100% handwritten and per-component: 29 `Forge*.tsx` files each call a shared + `createUnifiedWrapper()` factory with per-component prop/event mapping and a hand-authored SSR + fallback. This gives real typed props (`ForgeButtonProps`, etc.) but means **every new core + component requires a human to hand-author a new wrapper file** โ€” there is no codegen and no CI + check enforcing sync between `src/components/` and the wrapper package. Two elements + (`forge-toast-container`, `forge-performance-dashboard`) are unwrapped in all three packages, a + defensible gap for utility/singleton elements. +- **forge-vue and forge-angular are generic**: composables/directives/services that work against + any custom element, with zero per-component files. This achieves 100% coverage "by construction" + but provides **no Vue/Angular equivalent of typed component props** โ€” a real capability gap + relative to forge-react, not just a documentation gap. +- **CI treatment is asymmetric and this is the more urgent drift**: forge-react is built and + type-checked on every PR (`ci.yml`, `develop.yml`). forge-vue and forge-angular are **never + linted, type-checked, or built on any PR or push to develop** โ€” their `tsc` compile only runs for + the first time in `release.yml`, right before publishing. This already caused one shipped-broken + release (v1.0.0, silently missing compiled `dist/`, fixed in v1.0.1). None of the three wrapper + packages has a single test file, and none is linted by any script in the repo (root's `lint` + script only globs root `src/**/*.ts` plus forge-rhf). +- **CHANGELOG/version drift, confirmed and traced to root cause**: all four of forge-react, + forge-vue, forge-angular, and forge-rhf have a `CHANGELOG.md` topped by a `## 2.0.0` heading that + was never actually published. PR #69 (`fa2e3bb`, 2025-10-08) ran `changeset version`, bumped all + four to 2.0.0, then a follow-up commit in the *same* PR walked the `package.json` versions back + down to 1.0.5/1.0.2/1.0.2/1.0.2 (correct, patch-level) โ€” but never renamed the already-generated + changelog headings. For forge-vue and forge-angular, the string "1.0.2" (their real, live version) + **never appears anywhere in their changelog file**. Anyone reading the changelog for the version + they actually installed sees it filed under a version number that was never shipped. +- **Doc bug specific to Angular**: `docs/GETTING_STARTED.md:82-85` imports `ForgeModule`, which + **does not exist** โ€” the real export is `ForgeAngularModule`. Any user copy-pasting the official + quick-start gets an import error immediately. `docs/integrations/angular.md` compounds this by + hedging ("example names shown โ€” adjust to your package exports") about features + (`ForgeControlValueAccessor`, named directives) that are in fact concretely and correctly shipped + โ€” the doc is strictly worse than the package's own README. + +### 1.4 forge-rhf, forge-tokens: quieter but real defects + +- **forge-rhf** bundles the *entire* `@nexcraft/forge-react` package into its own `dist/index.js` + (42,857 bytes, confirmed via `npm pack`) because its Rollup externals list still references a + dead pre-split import path (`@nexcraft/forge/integrations/react`) instead of the real dependency. + Every consumer of forge-rhf therefore gets a second, duplicated copy of forge-react baked in on + top of their own peer-dependency install โ€” bundle bloat and a latent risk of duplicate custom-element + registration. The adapter logic itself (Controller wiring for 4 field types) is sound and builds + cleanly; it simply has zero test coverage despite `vitest` being wired up as if it did. +- **forge-tokens** works correctly for everything it actually implements (pull/normalize/validate/apply/diff + against sample data, verified end-to-end offline). But its one documented customization mechanism, + a `forge.figmaconfig.json` config file (documented in both the package README and + `docs/guides/figma-to-forge.md`), **does not exist in code at all** โ€” zero references outside the + docs themselves. This is vaporware, not drift. + +### 1.5 forge-mcp-figma: does not implement MCP, verified empirically + +This is the most consequential finding in the packages area. `packages/forge-mcp-figma/bin/server.mjs` +is a 53-line hand-rolled newline-delimited JSON-RPC-over-stdio script โ€” its own top comment admits +"Minimal MCP-like JSON-RPC over stdio." There is no `@modelcontextprotocol/sdk` dependency anywhere +in the repo (`grep -rl modelcontextprotocol` returns zero hits across the entire history). It never +implements the `initialize` handshake that the MCP spec (2024-11-05 and every revision since) +requires before any other method is valid, and it never implements `tools/list`/`tools/call` +discovery โ€” it expects the literal tool name as the top-level JSON-RPC method, which no +spec-compliant client sends. + +**Confirmed by spawning the real server and sending the literal first message any MCP client sends**: +an `initialize` request returns `{"error":{"code":-32000,"message":"Unknown method: initialize"}}`. +Any real MCP client โ€” Claude Desktop, Claude Code, Cursor, VS Code Copilot โ€” fails on connection, +full stop. The underlying tool logic (delegated to forge-tokens) does work when called directly with +its own custom method name, so this is purely a transport/protocol-compliance failure, not a logic +bug. It was scaffolded once (2025-09-29), published once (2025-10-02), and never touched again โ€” this +isn't spec drift from a moving target, it never conformed at any point. It still receives 23 +downloads/month, plausibly people discovering it doesn't work. The project's own roadmap doc +(`plans/priorities/02-short-term-roadmap.md:18-21`) marks "Forge MCP for Figma" as shipped (`[x]`) โ€” +reflecting "a package was published," not "the feature works as designed." + +--- + +## 2. Demo apps + +| Demo | Pinned `@nexcraft/forge` | Verdict | Notes | +|---|---|---|---| +| `demos/nextjs-app` | `^0.9.0` (capped, cannot reach 0.10.0 without a manual bump) | **alive** | Builds successfully end-to-end (`next build --turbopack`, only lint warnings). Carries a "TEMPORARY" local-CSS workaround (`layout.tsx:3-4`) for a tokens.css export gap that was actually fixed upstream in 0.10.0 two days after the workaround was written โ€” dependency was never bumped, workaround never removed. Own README instructs the now-fixed import path, contradicting the demo's actual source. Top-level `demos/README.md` also cites the wrong dev-server port (3000 vs actual 9091). | +| `demos/vue-app` | `^0.7.0` (3 minors behind) | **broken** | `npm run build` (`vue-tsc && vite build`) fails today with two permanent TypeScript errors (`TS6133`, `TS7006`) in `src/App.vue`, present since the file's last edit on 2025-10-08 โ€” not flaky, not environmental. Has been unbuildable via its own documented command for the entire 9-month dormancy. The demo's own `AI_TESTING_FEEDBACK.md` self-rates the package experience "2/5" and documents 3 real bugs found against the published package at the time (empty AI manifest, raw TS syntax shipped in compiled `.js`, missing `exports` subpath) โ€” src still carries defensive `try/catch` fallbacks distrusting the package. Top-level docs honestly flag this demo "In Progress," unlike Next.js's unqualified checkmark. | +| `demos/vanilla-app` | `0.7.1` (exact pin, oldest of the three) | **alive, with caveat** | Builds successfully, but only because `vite.config.ts` prefers a local `dist/nexcraft-forge.es.js` build when present, which existed in this checkout โ€” the actual pinned-npm-dependency code path was not independently exercised. Code quality is solid (JSDoc `@ts-check`, wires up 10+ interactive components with real sample data). | + +None of the three demos use workspace-protocol linking โ€” all resolve against real published npm +versions, all are at least one release behind current. + +--- + +## 3. Repo & ecosystem health + +### 3.1 Git analytics + +- **700 commits total** across all refs (525 reachable from `origin/develop`). Effectively + single-author: `ignis` (435 commits, `maildevcom+1@gmail.com`), then bots โ€” + `github-actions[bot]` 150, `dependabot[bot]` 25 โ€” plus `dev-ignis` (89 commits, ambiguous + human-alias-or-CI-identity). No other human contributor appears anywhere in `--all` history. +- **Cadence is a single 2.5-month sprint**: 41 commits Aug 2025, 508 in Sep 2025 (peak, ~17/day), + 140 in Oct 2025, 10 in Nov 2025, then 1 lone dependabot-triggered commit in Feb 2026 and nothing + since. First commit 2025-08-28; 60 published core-package versions (including ~30 betas) shipped + in under 6 weeks. +- **Tags**: last tag of any kind is `2025-10-08` (`@nexcraft/forge@0.10.0` and sibling 1.0.x/0.2.0 + tags). 28 separate `0.5.2-beta.N` tags were cut within a single 9-day span (Sep 6โ€“15) โ€” + indicative of a rough, iterate-in-production release process during the initial burn. +- **Local checkout caveat**: at analysis time, local `develop` was 4 commits behind + `origin/develop` (trivial: a merge, an auto-labeler PR, two dependabot merges) โ€” worth a `git + pull` before anyone resumes work, though it doesn't change the substantive picture. + +### 3.2 main โ†” develop divergence: unreleased work + +`origin/main...origin/develop` = **1 commit ahead on main, 99 commits ahead on develop**. The 1 +main-only commit is the last thing that happened to the repo pre-dormancy (a dependabot bump merged +2025-11-11). The 99 develop-only commits include real, shippable work that never reached npm because +no release was ever cut after 0.10.0/1.0.5 (2025-10-08): +- `137b562` "security: upgrade vite to 7.1.7 to fix esbuild vulnerabilities" โ€” **an unshipped + security fix**, meaning current npm consumers are missing a real CVE remediation. +- `fae863a` selective imports for all 28 components; `9e89a75` forge-card border prop; `cbf3881` + tokens.css export fix; `83d4fcf` expanded design tokens; ADR-008 native-button-pattern compliance + work across several commits; Storybook AI-panel addon; developer debugging utilities; SSR + architecture fix; changeset-requirement CI check. + +Anyone evaluating "what does the published package do" from npm alone is looking at a snapshot that +is missing nine months of accumulated (if unreleased) fixes. + +### 3.3 GitHub repository state + +- **1 star, 0 forks, 0 subscribers** โ€” negligible external adoption. +- **10 open PRs, 0 open issues** (GitHub's `open_issues_count` of 10 conflates PRs; filtering + confirms zero real issues). All 10 open PRs are Dependabot branches, all green CI, sitting + unmerged for **154โ€“231 days** as of 2026-07-13. Nobody has triaged a dependency PR since Nov 2025. +- **`Security Audit (Nightly)` workflow is now `disabled_inactivity`** โ€” GitHub's automatic 60-day + disabler fired, with the last successful run 2026-04-10. Combined with `pushed_at` = 2026-02-09 + (last git push of any kind, a dependabot branch) and `updated_at` = 2025-11-11 (last human-relevant + repo activity), this gives a precisely dated abandonment signature: dependabot โ†’ CI โ†’ nightly + security scan kept functioning correctly on autopilot for ~3 months after the human left, and is + only now starting to shut itself down from disuse. + +### 3.4 npm ecosystem reality + +Total monthly downloads across all seven packages (core + 6 workspace packages) sum to roughly +408/month โ€” low, roughly proportional to each package's complexity/usefulness, and flat (no growth +signal available without a paid trend API, but consistent with 1 star / 0 forks). Two additional +footguns found in registry metadata: +- **`beta` dist-tag is stale and would downgrade a user**: `npm dist-tag` shows + `{"beta": "0.8.0-beta.0", "latest": "0.10.0"}` โ€” installing `@nexcraft/forge@beta` today pulls an + *older* version than stable. +- A chaotic, numerically-inconsistent `0.7.2-beta.0` version appears in the history of all six + workspace packages simultaneously (all timestamped within seconds on 2025-09-30), consistent with + a botched Changesets pre-release exit โ€” these versions remain resolvable on the registry. + +### 3.5 Dependency drift (installed vs. latest available, 2026-07-13) + +| Dependency | Installed | Latest | Drift | +|---|---|---|---| +| `typescript` | 5.9.3 | 7.0.2 | **2 majors behind** | +| `vite` | 7.1.9 | 8.1.4 | 1 major behind | +| `vitest` | 3.2.4 | 4.1.10 | 1 major behind | +| `storybook` (+ addons) | 9.1.10 | 10.5.0 | 1 major behind | +| `eslint` | 9.37.0 | 10.7.0 | 1 major behind | +| `lit` | 3.3.1 | 3.3.3 | 2 patches behind (low risk) | +| `tailwindcss` | 4.1.14 | 4.3.2 | same major, several minors | +| `happy-dom` | 20.0.2 | 20.10.6 | same major, several minors/patches | + +Every major-version gap already has a corresponding open, CI-green, unmerged dependabot PR โ€” this +is explained entirely by 9 months of nobody clicking merge, not by unusual internal neglect. + +### 3.6 Committed-artifact bloat: none found + +`dist/`, `coverage/`, `storybook-static/`, `custom-elements.json`, and `node_modules/` all exist on +disk as local leftovers but **none are git-tracked** โ€” confirmed via `.gitignore` coverage and +`git ls-files`/`git log --all -- ` returning empty for all four across all of history. Pack +health is clean: 1,511 objects, 9.25 MiB, zero garbage/dangling objects, 16M total `.git`. This is +the one unambiguously healthy signal in an otherwise stale picture. + +### 3.7 `.env` finding + +An untracked, correctly `.gitignore`d `.env` (486 bytes, dated 2025-09-30) sits at repo root +containing `DISCORD_WEBHOOK_URL`, `DISCORD_WEBHOOK_CRITICAL`, `DISCORD_WEBHOOK_OPS`, and +`NPM_TOKEN` keys. Confirmed never committed at any point in git history. Not an incident, but it +means a live npm-publish token and Discord webhooks sit unencrypted on disk for a project whose +GitHub side is otherwise fully dormant โ€” worth rotating/securing before any revival work resumes on +this machine or a shared one. A repo-wide secret-pattern grep over tracked files found no actual +hardcoded secrets (only legitimate `${{ secrets.* }}` GitHub Actions references and doc placeholders). + +### 3.8 npm registry ownership: bus factor of 1 + +All six published `@nexcraft/*` packages list an **identical single npm maintainer**: `rollg +` โ€” no co-maintainer, no npm org/team account, on any package. The GitHub +identity everything points to, `dev-ignis`, is confirmed via the GitHub API to be a **personal User +account, not an Organization**. The dominant git commit author, `ignis ` +(435 commits), is a Gmail plus-alias of the exact same base address as the npm maintainer email โ€” +and that address is also this analysis session's own configured user email, confirming the current +owner and the original builder are the same person. `package.json`'s `"author": "Ignis Team"` is +the only place a "team" is asserted anywhere, and every other data source (npm maintainers, GitHub +org lookup, git shortlog) contradicts it. No `CODEOWNERS`, `SECURITY.md`, `GOVERNANCE.md`, or +`CONTRIBUTING.md` exists anywhere in the repo. Publishing runs through a single shared `NPM_TOKEN` +GitHub Actions secret with **no provenance/OIDC attestation** on the stable release path +(`release.yml` lacks `id-token: write`; the beta workflow has the permission but never passes +`--provenance`, so it's vestigial). This is a genuine single-point-of-failure for the entire public +surface of the library. + +### 3.9 License consistency: not consistent, two packages are unlicensed on npm + +Root and 4 of 6 packages (forge-react, forge-vue, forge-angular, forge-rhf) declare `"license": +"MIT"`, matching the root `LICENSE` file exactly. **`forge-mcp-figma` and `forge-tokens` have no +`license` field at all** โ€” not `"UNLICENSED"`, simply absent โ€” confirmed both in the local +`package.json` files and live on the npm registry (`license: undefined` via the registry API for +both). Neither package ships a `LICENSE` file in its `files[]` allowlist, and npm workspaces do not +auto-copy the monorepo root LICENSE into sub-package tarballs. Traced via git log: the field was +never present from the packages' inception commit (`40c3631`) through their actual publish +(`3c95e51`) โ€” not stripped later, never added. Practical effect: automated SCA/license-compliance +tooling (FOSSA, Snyk, license-checker) will flag both packages as unlicensed/unknown for anyone who +runs a compliance scan against them today. + +--- + +## 4. Ranked risks + +1. **Bus factor of 1 with no succession plan.** One person controls the GitHub repo (personal + account, not an org), the npm account, and the sole CI publish token, with no provenance + attestation and no governance docs. If this person becomes unavailable, there is no path for + anyone else to ship a patch to any of the six packages. +2. **`forge-mcp-figma` is non-functional as advertised and still being downloaded.** It has never + implemented the MCP handshake; every real MCP client fails on connection. It's live on npm, + documented as working, and marked "done" on the roadmap. +3. **forge-vue and forge-angular ship with zero automated quality gates** (no lint, no tests, no + PR-time type-check or build) โ€” verification only happens in the release workflow itself, which + already produced one broken release (v1.0.0). A silent regression on the next release is a live + possibility with no CI to catch it. +4. **A real, unshipped security fix sits on `develop`.** The Vite/esbuild CVE upgrade (`137b562`) is + one of 99 commits never released to npm; current consumers of the published packages don't have it. +5. **The public-facing surface actively misleads a new user.** Wrong GitHub org in the README's own + clone command (`nexcraft/forge`, 404) contradicting the correct `package.json` metadata + (`dev-ignis/forge`); dead GitHub Pages/Storybook links in both the "correct" and "incorrect" org; + a broken `ForgeModule` import in the official Angular quick-start; four packages' changelogs + permanently headed by a `2.0.0` release that was never actually published; a stale `beta` dist-tag + that downgrades on install. +6. **Two publicly-installable packages have no license metadata**, which will fail automated + compliance scanning for any downstream adopter with SCA tooling in their pipeline. +7. **Both non-React demos have real problems**: `vue-app` has been unbuildable via its own + documented command since the day it was last touched; `nextjs-app` carries a superseded + "TEMPORARY" workaround and points users at an import path its own dependency pin can't yet supply. +8. **`forge-rhf` silently bundles all of `forge-react`** into its output due to a stale externals + config, doubling consumers' bundle weight for a package that only uses 4 of forge-react's 29 + components. +9. **Ten open, green-CI dependabot PRs sit unmerged for 5โ€“7.5 months**, with `typescript` now two + majors and `vite`/`vitest`/`storybook`/`eslint` each one major behind current. + +--- + +## 5. Recommendations + +**If reviving, do these first (cheap, high-signal-to-cost):** +- Merge or triage the 10 open dependabot PRs; they're already green. +- Cut a real release from `develop` to ship the 99 pending commits, prioritizing the Vite/esbuild + security fix. +- Fix the four stale `CHANGELOG.md` "2.0.0" headings and the `ForgeModule` โ†’ `ForgeAngularModule` + doc bug; both are minutes of work and both currently mislead real users. +- Fix the README's wrong GitHub org / dead Pages links, and the stale `beta` npm dist-tag. +- Add `"license": "MIT"` to `forge-tokens` and `forge-mcp-figma` and republish; trivial and closes a + real compliance gap. +- Make an explicit call on `forge-mcp-figma`: either implement the actual MCP SDK/handshake, or pull + it from npm / clearly mark it non-functional. Leaving it live and undocumented-as-broken is the + single most reputationally risky item in the repo given it's the "AI-native" headline feature. + +**Medium effort, before treating this as production-ready:** +- Wire forge-vue and forge-angular into the existing PR-time lint/type-check/build pipeline that + forge-react already has; add at least smoke tests for both. +- Fix forge-rhf's Vite externals so it stops bundling all of forge-react. +- Fix `demos/vue-app`'s two TypeScript errors and bump `demos/nextjs-app`'s pinned versions, + removing the superseded "TEMPORARY" CSS workaround. +- Replace the `workspace:*` devDependency with a real npm-supported range (`"*"` or `file:`). + +**Structural, before depending on this long-term:** +- Address the bus-factor-of-1 directly: add a second npm co-maintainer and GitHub collaborator, + rotate the shared `NPM_TOKEN`, and add `--provenance`/OIDC to the stable release workflow. +- Decide whether `forge-tokens` and `forge-mcp-figma` are worth continued investment given their low + usage (47 and 23 downloads/month) relative to their gaps, or whether narrowing scope to the core + library + React/Vue/Angular wrappers is the more defensible footprint to maintain going forward. + +--- + +*Sources: analyst notes at `pkg-frameworks.md`, `pkg-tooling.md`, `health.md`, +`npm-registry-ownership.md`, `license-consistency-check.md` (this job's `tmp/forge-analysis/` +directory). All figures cited are as captured in those notes on 2026-07-13; repo access was +read-only throughout.* diff --git a/plans/analysis-2026-07/06-documentation-audit.md b/plans/analysis-2026-07/06-documentation-audit.md new file mode 100644 index 0000000..a7501e6 --- /dev/null +++ b/plans/analysis-2026-07/06-documentation-audit.md @@ -0,0 +1,142 @@ +# Documentation Audit โ€” @nexcraft/forge v0.10.0 + +Repo: `/home/air_buster/rollg/ignis/apps/forge` (branch `develop`, dormant since 2025-10-15) +Audience: project owner deciding whether/how to revive the project. + +## TL;DR + +The docs are extensive (71 markdown files under `docs/`, plus README, AGENTS.md, CHANGELOG, and AI-metadata JSON) and the folder taxonomy is sound in principle. But the corpus has visibly drifted out of sync with itself across two structural changes โ€” the flatโ†’`atoms/molecules/organisms` component-doc reorg and the monorepo framework-package split โ€” and nobody ran a consistency pass afterward. Concretely: **22% of internal doc links are dead** (52/238), the README contradicts itself on component count five different ways in the same file, three of six spot-checked component API docs contain fabricated properties/events that don't exist in source, and โ€” worst of all โ€” the two files written specifically to steer AI coding assistants (`claude-instructions.md`, `.cursorrules`) instruct them to generate an import statement that was removed as a documented breaking change and structurally does not exist in `package.json`'s `exports` map. The "AI-native" pitch is the product's core differentiator, and it is the most broken part of the documentation. None of this is unfixable โ€” it's mechanical drift, not conceptual rot โ€” but a revival should not point new AI-assisted contributors at the current docs without a cleanup pass first. + +## 1. Inventory + +| Location | Files | Notes | +|---|---|---| +| `docs/` (root-level) | 14 | CONTRIBUTING, DEVELOPER_GUIDE, GETTING_STARTED, README, REPOSITORY-STRUCTURE, SECURITY, ai-manifest, component-annotation-guidelines, git-workflow, performance-dashboard-api, performance-monitoring, publishing-deployment-strategy, semantic-html-best-practices | +| `docs/guides/` | 14 | | +| `docs/integrations/` | 8 | react, vue, angular, react-hook-form, nextjs-integration, nextjs-15-app-router, remix, sveltekit | +| `docs/theming/` | 3 | token-bridge, token-migration-guide, token-reference | +| `docs/ai/` | 2 | integration-guide, metadata-reference | +| `docs/components/` | 30 | 1 hub README + atoms (14) + molecules (8) + organisms (7) | +| **`docs/` total** | **71** | matches `find docs -type f \| wc -l` | +| Repo root, docs-adjacent | 6 | README.md (580 lines), AGENTS.md, claude-instructions.md, .cursorrules, CODE_OF_CONDUCT.md, CHANGELOG.md | +| `plans/` (not under docs/, heavily cross-linked from it) | โ€” | phases/, priorities/, adrs/ | +| Machine-readable AI metadata (repo root, shipped via `package.json` `files`) | โ€” | `ai-index.json` (12KB), `ai-manifest.json` (157KB), `ai-manifest.schema.json`, `custom-elements.json` (1.38MB) | +| `storybook-static/` | โ€” | a pre-built Storybook export committed to the repo, dated Oct 7 2025 | + +Component doc **file-existence coverage is 100%**: all 29 real components (14 atoms, 8 molecules, 7 organisms โ€” note `atoms/progress/` folder holds two components, `progress.ts` and `progress-circle.ts`) have a matching `docs/components/{category}/{name}.md`. Two additional shipped custom elements have no page: `forge-toast-container` (gets only a sub-section inside `toast.md`, acceptable) and `forge-performance-dashboard` (`src/utils/performance-dashboard.ts`, genuinely undocumented anywhere). + +## 2. Accuracy findings, worst first + +### 2.1 CRITICAL โ€” AI-instruction files teach a broken, removed import path + +`claude-instructions.md` and `.cursorrules` (byte-identical except the title line, confirmed via `diff`) instruct AI coding assistants, in five places (lines 14, 17, 108, 131, 158), to generate: + +```javascript +import { ForgeButton, ForgeInput, ForgeCard } from '@nexcraft/forge/integrations/react' +import { RHFForgeInput, RHFForgeSelect } from '@nexcraft/forge/integrations/rhf' +``` + +`CHANGELOG.md`'s own 0.9.0 entry ("Phase 15 Complete: Framework Integration Package Split") documents this exact path as a **BREAKING CHANGE**, replaced by `@nexcraft/forge-react`. `package.json`'s `exports` map has no `./integrations/react` or `./integrations/rhf` key at all โ€” the path is not deprecated, it structurally does not resolve. Any AI assistant (Cursor, Claude) following these files verbatim generates code that fails to import. The same broken path also appears inside `docs/components/atoms/button.md` (lines 33, 260, 278). By contrast, root `README.md` (L21, L239-242) correctly documents `@nexcraft/forge-react` โ€” so the fix is known and already written down elsewhere, it just wasn't propagated to the files AI tools are told to read first. + +The same two files also point at `./docs/ai-methods.md` (line 7), which doesn't exist, and reference an `./ai-tools/` directory (lines 216-217, 241) that is wired into `package.json`'s `exports`/`files` config but was never built โ€” confirmed absent from the real published npm tarball (`npm pack @nexcraft/forge --dry-run`, 0.10.0, 136 files, no `ai-tools/*` entries). + +### 2.2 HIGH โ€” Component API docs contain fabricated properties and events + +Spot-checked 6 of 29 components by diffing `@property()` declarations in source against each doc's Properties/Events table: + +| Component | Verdict | Detail | +|---|---|---| +| `button.ts` vs `atoms/button.md` | **Inaccurate** | Doc lists `rippleDisabled`, `autoFocus` (0 hits in source) and events `forge-click`, `loading-start`, `loading-end` (source only emits plain `click`). Real props `iconStart`/`iconEnd` (button.ts:314-315) are missing from the doc; every doc example instead uses ``, which the component's own internal warning explicitly discourages (button.ts:156). | +| `select.ts` vs `atoms/select.md` | **Inaccurate** | Doc lists 7 properties with zero occurrences in source (`clearable`, `helpText`, `maxHeight`, `multiple`, `searchPlaceholder`, `success`, `warning`). Real properties are missing entirely, including `options` โ€” the list of selectable options, arguably the component's most important prop. | +| `data-table.ts` vs `organisms/data-table.md` | **Inaccurate** | Doc documents `dataError`, `expandedRows`, `selectedRows`, `sortColumn`, `sortDirection` as public settable properties; source declares all five `@state() private` (internal Lit state, not public API). Real public props `pageSize`, `selectionMode`, `showPagination`, `responsiveMode` are absent from the doc. | +| `toast.ts`/`toast-container.ts` vs `molecules/toast.md` | **Mixed** | `ForgeToast` half matches source exactly. `ForgeToastContainer` sub-table documents `spacing`/`autoRemoveDelay`, neither a real `@property`; real prop `stackNewest` is undocumented. | +| `tree-view.ts` vs `organisms/tree-view.md` | Accurate | All 6 properties match, including kebab-case attribute names. | +| `avatar.ts` vs `atoms/avatar.md` | Accurate | All properties match. | + +**3 of 6 have concrete, verifiable inaccuracies.** These are exactly the docs the "AI-native" pitch says agents should read to generate code โ€” a reader (human or AI) trusting these tables produces components with nonexistent attributes and dead event listeners. + +### 2.3 HIGH โ€” Component count contradicts itself five ways within README.md + +- L18: "26+ components" +- L128: "31 components" +- L257: "26 components" +- L265 + L434: "Atoms (12 components)" / "Total: 27 (12+8+7)" โ€” undercounts the real 14 atoms by omitting `forge-avatar` and `forge-progress-circle` +- L499: "27 components" +- `ai-index.json`'s `summary.totalComponents`: **31** โ€” the only rigorously computed number, and it agrees with none of the prose + +`forge-avatar` has full source and a complete, accurate doc page but is never mentioned anywhere in README.md (`grep -c avatar README.md` โ†’ 0) โ€” absent from the Component Index, the Atoms showcase table, and the count math. + +### 2.4 MEDIUM-HIGH โ€” 22% of internal doc links are dead (52 of 238 checked) + +A full scan of `[text](target)` links across README, AGENTS.md, claude-instructions.md, .cursorrules, CODE_OF_CONDUCT.md, CHANGELOG.md, and everything under `docs/**` found 52 confirmed-dead internal links, in four patterns: + +- **README โ†’ flat component paths (9 links, README.md L420-431):** links to `docs/components/{name}.md` for button/input/icon/alert/checkbox/badge/switch/radio-group/select โ€” the files live under `docs/components/atoms/{name}.md`. The next 3 rows in the same table correctly use the `atoms/` prefix, showing the reorg happened mid-table and the older rows were never fixed. +- **Component-to-component "Related Components" links (~30 links across โ‰ฅ13 files):** every one still points at the pre-reorg flat structure, e.g. `docs/components/atoms/avatar.md` links to `../button.md` instead of `./button.md`; `docs/components/organisms/data-table.md`, `tree-view.md`, `accordion.md`, `pagination.md`, `tabs.md`, `navigation-bar.md`, and `docs/components/molecules/multi-select.md` all have the same issue. +- **Dangling `./spinner.md` references (3 links):** `progress.md`, `progress-circle.md`, `skeleton.md` all link to a component that doesn't exist in `src/` either โ€” likely planned/renamed but never shipped. +- **Named-but-missing peripheral docs:** `docs/troubleshooting.md`, `docs/api-reference.md`, `docs/accessibility-testing-guide.md`, `plans/architecture/component-architecture.md`, `docs/examples/` are referenced but don't exist; `docs/performance-monitoring-guide.md` and `docs/theming/migration-guide.md` are referenced under the wrong filename (real files: `performance-monitoring.md`, `token-migration-guide.md`). + +### 2.5 MEDIUM โ€” `docs/patterns/` is referenced everywhere and exists nowhere + +`package.json`'s `files` array (line 24) lists `docs/patterns/` for publishing; it does not exist. Cross-referenced from `package.json`'s `examples`/`patterns` URLs (lines 268, 271), `claude-instructions.md`/`.cursorrules` (line 243), `.github/copilot-instructions.md` (line 243), and the deployed site's own nav (`.github/workflows/deploy.yml` emits a `` button that 404s). `plans/priorities/01-immediate-priorities.md` (line 407) checks this off as done โ€” "โœ… Fix documentation shipping issues (added docs/patterns/ to package.json)" โ€” but only the package.json entry was added, never the directory. `AI_COMPONENT_CATALOG.md` and `AI_COMMON_PATTERNS.md`, which CHANGELOG's 0.8.0 entry claims were created, don't exist anywhere in the repo. + +### 2.6 MEDIUM โ€” README points at a GitHub org that doesn't exist + +`package.json`, `claude-instructions.md`, `.cursorrules`, and `demos/README.md` all correctly reference `github.com/dev-ignis/forge`. But README.md โ€” the most user-facing doc โ€” uses `github.com/nexcraft/forge` twice (L223 clone command, L530 GitHub link), matching the npm scope but not the actual org. Verified live: `nexcraft/forge` โ†’ 404, `dev-ignis/forge` โ†’ 200. + +### 2.7 MEDIUM โ€” Storybook link is dead by three different routes, and "Coming Soon" is false + +README.md L531 says Storybook is "Coming Soon" at `nexcraft.github.io/forge`. In reality a `gh-pages` branch was last deployed 2025-09-08, a month before README's Oct 8 edit โ€” so "Coming Soon" was already stale when written. All three plausible URLs are currently dead: the README's own URL (wrong org, 404), the CNAME'd custom domain `forge.ignis.dev` from the gh-pages branch (DNS resolution failure), and the org-correct `dev-ignis.github.io/forge/` (301-redirects into the dead custom domain). A full Storybook build sits in the repo (`storybook-static/`, Oct 7 2025) and the deploy pipeline (`.github/workflows/deploy.yml`) is coherent โ€” it's just serving a domain that no longer resolves. + +### 2.8 MEDIUM โ€” AGENTS.md describes the pre-monorepo-split architecture + +AGENTS.md (last touched Sep 16 2025) says framework bindings live at `src/integrations/{react|vue|angular}` (L7) โ€” that directory doesn't exist; per CHANGELOG, framework integrations were extracted into standalone packages (`packages/forge-react`, etc.) before AGENTS.md's last edit. It also says examples live in `examples/` and `demo/` (L9); the real directory is `demos/` (plural). This matters more than typical staleness because `docs/REPOSITORY-STRUCTURE.md` explicitly defers all structural authority to AGENTS.md ("single source of truth"), so the staleness propagates to the one doc whose entire job is describing repo layout. + +### 2.9 LOW-MEDIUM โ€” Generated AI metadata has a categorization bug + +`ai-index.json`'s `summary.categories` reports `{"atom": 31}` โ€” every component, including organisms (`forge-data-table`, `forge-tree-view`) and molecules (`forge-modal`, `forge-toast`), is mistagged "atom." This is shipped data (published to npm, importable as `@nexcraft/forge/ai-index.json`), not prose โ€” a bug in `scripts/generate-ai-index.js`'s categorization logic, not a typo. + +### 2.10 LOW โ€” CHANGELOG has duplicate version headers and a stale trailing inventory + +`## 0.9.0` appears twice as a top-level header (line 79: tree-shaking/test refactor; line 130: framework-package split + Figma tokens) and `## 0.8.0` appears twice (line 119 brief; line 196 longer, different content) โ€” likely an artifact of the Changesets tool merging `main`/`develop` release trains without consolidation. The trailing "Component Inventory" section (lines 323-329) claims "23+ Production-Ready Components... Atoms (9), Molecules (8), Organisms (6)" โ€” a v0.4.0-era snapshot that was never updated as atoms grew 9โ†’14 and organisms 6โ†’7, sitting directly below accurate 0.10.0 entries at the top of the same file. + +## 3. Consistency and duplication + +- The "AI Manifest Files" narrative (README L33-130) is substantially re-told across 5 files โ€” README.md, `docs/ai/integration-guide.md`, `docs/ai/metadata-reference.md`, `docs/guides/ai-native-development.md`, `claude-instructions.md`/`.cursorrules` โ€” with the same ChatGPT/Claude/Copilot code samples repeated rather than referenced from one source. There is no single canonical source for the 3 AI methods, and changes evidently aren't propagated consistently โ€” this is exactly how the broken import path in ยง2.1 survived while README's own copy was fixed. +- The "Design Token Bridge" (`TokenBridge.fromFigma(...)`) pitch is duplicated word-for-word **within README.md itself** (L144-148 and L316-327). +- `docs/components/README.md` (the component hub) and root README's "Components Showcase" maintain two independently stale component listings that don't agree with each other or with `src/` (see ยง2.3). The hub specifically omits `aspect-ratio.md`, `progress.md`, `progress-circle.md`, `skeleton.md`, and `data-grid.md` from its category lists (Atoms list has 10/14, Organisms 6/7) even though the doc files exist on disk โ€” they're simply undiscoverable from the index. +- `docs/README.md` (the docs/ index) doesn't link to `docs/components/` at all, nor to `component-annotation-guidelines.md`, `semantic-html-best-practices.md`, or 4 of the 8 integration guides (`nextjs-15-app-router.md`, `react-hook-form.md`, `remix.md`, `sveltekit.md`). Root `CHANGELOG.md` has no link from `docs/README.md` either โ€” it's fully disconnected from the docs index. + +## 4. What's missing + +- `docs/patterns/` directory (ยง2.5) โ€” referenced from `package.json`, both AI-instruction files, and the deployed site nav; never created. +- `ai-tools/` directory (ยง2.1) โ€” wired into `package.json` exports/files but never built; a whole promised layer of per-component, per-framework JSON schemas that doesn't exist. +- `AI_COMPONENT_CATALOG.md`, `AI_COMMON_PATTERNS.md` โ€” claimed created in CHANGELOG 0.8.0, absent from the repo entirely. +- `docs/troubleshooting.md`, `docs/api-reference.md`, `docs/accessibility-testing-guide.md`, `plans/architecture/` โ€” referenced from multiple docs, never created. +- A doc page for `forge-performance-dashboard` (`src/utils/performance-dashboard.ts`) โ€” the one genuinely undocumented shipped component. +- A working, resolvable Storybook URL (ยง2.7). + +## 5. Marketing claims vs. reality + +- "The FIRST AI-Native component library" / "Industry First!" (README L14, L298, L316, L354) โ€” unverifiable superlative, not checkable from the repo. +- Component count claims (ยง2.3) โ€” directly checkable, directly contradicted 5 ways in one file. +- "<10KB per component" / "<10KB" bundle size badge (README L4, L360, L508) โ€” not verified in this pass; would require building and measuring chunks. +- Test coverage: badge says **86.4%** (L5), body text says **87.2%** (L435) and "**90%+**" (L463) โ€” three different numbers in one file; `coverage/index.html` on disk (dated 2025-10-03) was never used to reconcile them. +- "Storybook (Coming Soon)" โ€” already deployed (to what is now a dead URL) a month before this line's last edit (ยง2.7). +- The `.storybook/addons/ai-panel/` custom Storybook addon appears to be a genuine, non-trivial AI-metadata panel โ€” a legitimately distinctive feature, not just copy โ€” but wasn't evaluated for correctness in this pass. + +**Overall honesty assessment:** the underlying "AI-native" concept (machine-readable `ai-index.json`/`ai-manifest.json`, a JSON Schema, a custom Storybook AI panel) is real and reasonably well-executed as an idea. But the docs oversell its current state (dead Storybook link marked "Coming Soon," an `ai-tools/` layer that doesn't exist, a categorization field that's 100% wrong) and โ€” critically โ€” the two files whose entire purpose is steering AI assistants contain a broken import path that would cause those exact tools to generate non-functional code. That gap between pitch and reality is the single most damaging finding for a project marketing itself on AI-friendliness. + +## 6. Recommendations + +If reviving, fix in this order โ€” each is small in isolation but they compound: + +1. **Fix `claude-instructions.md` and `.cursorrules`** (ยง2.1) first โ€” they're identical, so one edit fixes both. Replace `@nexcraft/forge/integrations/react` and `/integrations/rhf` with `@nexcraft/forge-react`, remove the `./ai-tools/` and `./docs/ai-methods.md` references (or build `ai-tools/` and follow through). This is the highest-leverage fix: it's actively misleading the exact audience (AI coding assistants) the project claims to serve. +2. **Re-verify and fix the 3 inaccurate component docs found here** (button, select, data-table โ€” ยง2.2), then extend the same source-vs-doc diff to the remaining 23 components before trusting any of them for AI-assisted code generation. +3. **Run a link-check pass** across README + docs/** and fix the two structural patterns driving 39 of 52 dead links: the 9 flat-path links in README's showcase table, and the ~30 un-migrated "Related Components" links left over from the atoms/molecules/organisms reorg (ยง2.4). Both are single find-and-replace-shaped fixes, not one-off edits. +4. **Reconcile the component count** to one number (the AI-manifest's rigorously-computed 31, or 29 if toast-container/performance-dashboard are excluded) and propagate it to README's 5 conflicting locations and `docs/components/README.md`'s hub lists (ยง2.3). +5. **Decide on `docs/patterns/`** (ยง2.5): either build it (it's referenced from `package.json`, the AI-instruction files, and the live site nav) or strip every reference to it. Currently it's a checked-off TODO that was never actually done. +6. **Fix the GitHub org** (`nexcraft/forge` โ†’ `dev-ignis/forge`) in README.md (ยง2.6) and either fix the CNAME/deploy the correct domain or drop the dead Storybook link and claim (ยง2.7) โ€” a live Storybook is a strong asset for reviving interest and the build already exists in the repo. +7. **Update AGENTS.md** to reflect the post-monorepo-split layout (ยง2.8) โ€” this is the doc `docs/REPOSITORY-STRUCTURE.md` defers to, so fixing it fixes a second doc for free. +8. Lower priority, do during a broader cleanup: consolidate the CHANGELOG's duplicate 0.8.0/0.9.0 headers and delete or update the stale trailing inventory (ยง2.10); fix the `ai-index.json` categorization bug in `scripts/generate-ai-index.js` (ยง2.9); pick one canonical location for the AI-methods narrative instead of 5 (ยง3); reconcile the three different coverage-badge numbers (ยง5). + +None of these require architectural decisions โ€” they're consistency and truth-in-labeling fixes on top of a docs structure that's fundamentally reasonable. The AI-instruction fix (#1) and component-doc accuracy fixes (#2) should happen before any AI-assisted development resumes on this codebase, since the current docs would actively steer an AI agent toward broken code. diff --git a/plans/analysis-2026-07/07-roadmap-assessment.md b/plans/analysis-2026-07/07-roadmap-assessment.md new file mode 100644 index 0000000..bd630ad --- /dev/null +++ b/plans/analysis-2026-07/07-roadmap-assessment.md @@ -0,0 +1,189 @@ +# Roadmap & Plans Assessment โ€” @nexcraft/forge + +**Purpose:** For an owner deciding whether/how to revive this project, this document answers three questions: (1) what did the team say it was building, (2) what does the code actually contain, and (3) where do those two diverge. All findings below are drawn from a full read of `plans/README.md`, `plans/implementation-roadmap.md`, all 18 files in `plans/adrs/`, all 16 files in `plans/phases/`, and all 4 files in `plans/priorities/`, cross-checked against `git log`, `npm view`, and targeted `find`/`grep` passes over `src/` and `packages/`. Repo HEAD is `73f3b59` (2025-10-15, the last commit before the project went dormant). Today is 2026-07-13 โ€” roughly nine months of inactivity. + +**Bottom line up front:** the plans tree is not a reliable map of the codebase. It over-reports failure in some areas (features shipped but the checklist was never flipped) and under-reports it in others (a master roadmap table that silently omits four phase docs, one of which โ€” SSR โ€” is a completed, published, headline feature). Anyone reviving this project should treat `plans/` as a rich but stale historical record, verify status against code/npm before acting on any single claim, and budget time to reconcile or delete the ~40% of planning docs that are now actively misleading. + +--- + +## 1. ADR Index (18 ADRs + `plans/adrs/README.md`) + +All ADRs live in `plans/adrs/ADR-0NN-*.md`. "Reality check" reflects whether the decision is actually implemented in the current codebase/package structure, not just whether the ADR text is internally coherent. + +| ID | Title | Status (as written) | One-line essence | Reality check | +|---|---|---|---|---| +| ADR-001 | Web Component Abstraction Layer Selection | Accepted | Use Lit 3.x, not Stencil/pure WC/wrappers/transpilers. | Holds โ€” repo is built on Lit 3; no evidence of a framework switch. | +| ADR-002 | Shadow DOM for Style Encapsulation | Accepted | Shadow DOM by default, CSS Custom Properties as the theming escape hatch. | Holds โ€” consistent with component structure across atoms/molecules/organisms. | +| ADR-003 | CSS Custom Properties for Theming System | Accepted | Hierarchical CSS-variable token system (foundation โ†’ semantic โ†’ component). | Holds for the token *system*; the Phase 11 "Brand Kit" build-out on top of it never shipped (see ยง2, ยง3). | +| ADR-004 | Comprehensive Testing Strategy | Revised (Vitest replaces Web Test Runner) | Vitest+Happy DOM (unit), Chromatic (visual), Playwright (e2e, future), a11y layer. Coverage threshold lowered 90%โ†’80% in Jan 2025. | Partially stale โ€” ADR's own "80% current coverage ~85%, 313 tests" snapshot (Jan 2025) is superseded by `priorities/01-immediate-priorities.md`'s later claim of "1147 fast unit tests + 35 a11y tests" (Oct 2025); ADR was never refreshed with the newer number. Not independently re-run in this pass. | +| ADR-005 | Build Tooling and Module Bundling Strategy | Accepted | Vite dev + Vite Library Mode (Rollup) for production builds. | Holds โ€” no competing build tool found. | +| ADR-006 | State Management Architecture | Accepted | Strict "properties down, events up," no framework-specific state coupling. | Holds โ€” consistent with the framework-wrapper pattern used across `packages/forge-{react,vue,angular}`. | +| ADR-007 | Framework Integration Strategy | Accepted | Thin framework-specific wrapper utilities around core Web Components. | Holds structurally, but the *packaging* of that strategy changed later: what ADR-007 describes as wrapper utilities became fully separate, independently versioned npm packages under Phase 15 (see below) โ€” a reasonable evolution, but ADR-007 was never amended to say so. | +| ADR-008 | Component API Design Standards | Accepted, revised 2025-01-02 | Naming/attribute/event conventions; 2025-01-02 revision mandates native `