Skip to content

feat: run orphaned checks — template-standard CI validation and scripts/ type-checking (#483) - #491

Merged
GeraBart merged 1 commit into
constructorfabric:developfrom
tscbmstubp:feature/483-run-orphaned-checks
Aug 13, 2026
Merged

GeraBart merged 1 commit into
constructorfabric:developfrom
tscbmstubp:feature/483-run-orphaned-checks

Conversation

@tscbmstubp

@tscbmstubp tscbmstubp commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Closes #483.

Part 1 — template-standard/ checks now run in CI

New template-validate job in main.yml:

  • Builds the ecosystem packages the template file:-links (mfes, gts-plugin, api) first, since npm installs those as symlinks and the template packages build against their dist/.
  • Globs template-*/ and runs each template's own npm ci + build + arch:deps + lint + test:unit — no hardcoded template names, so the job survives the planned template-shell/template-mfe split (Split template-standard into template-shell + template-mfe #470) unchanged.

Running the checks locally immediately surfaced two breakages that had rotted unenforced, proving the issue's point:

  1. Template build was broken on develop: c679f1f moved FRONTX_ACTION_LOAD/MOUNT/UNMOUNT_EXT from @gears-frontx/mfes to @gears-frontx/gts-plugin, but 8 files in the template's framework package still imported them from mfes. Imports re-pointed (gts-plugin was already a declared peer dep; downstream consumers go through framework's re-export chain, so nothing else changed).
  2. 15 lint errors from the compiler-powered react-hooks v6 rules (refs-during-render, set-state-in-effect) across the react package hooks and demo screens. All fixed with behavior-preserving restructures (render-time state adjustment, lazy useState initializers, deriving instead of storing) — no eslint-disable for these. The only disable added is on TanStack Table's useReactTable (incompatible-library is informational: the React Compiler skips that component). Also added dist-lib/ to the template's eslint ignores.

Part 2 — scripts/ is now type-checked

  • New tsconfig.scripts.json: Node lib, types: ["node"], checkJs for the JSDoc-typed .mjs tooling; scripts/manual-auth-tests/ excluded (run-by-hand demos importing template-owned packages not resolvable from the ecosystem root).
  • Wired in as type-check:scripts inside type-check:all, so the existing CI step covers it with no workflow change.
  • First-run backlog was ~48 errors — all fixed with type-only changes: proper typedefs (PackageJson, Project), narrowing production signatures to the structural subsets they consume (SpawnedChildLike, DirEntryLike, FileSystemLike) instead of casting test fakes, and JSDoc return-type drift corrections in ecosystem-version-policy.mjs. No runtime behavior changes.

Also widened the check-json pre-commit exclude from tsconfig.json to tsconfig*.json (tsconfigs are JSONC).

Verification

  • Root: lint, type-check:all (now incl. scripts), arch:check, test:unit — all exit 0; script tests 183/183.
  • Template: arch:deps, lint, build:packages, test:unit — all exit 0.

Out of scope (known leftovers)

  • Template arch:deps:sdk/framework/react still reference ../internal/ — tracked as a sub-task on Split template-standard into template-shell + template-mfe #470.
  • One pre-existing type error in the template's ExtensionDomainSlot.test.tsx (mock missing new TypeSystemPlugin members) — only surfaces via the template's own type-check, which CI doesn't run yet.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved template app behavior when switching bridge instances, including theme, language, subscriptions, and text direction updates.
    • Ensured right-to-left languages correctly update text direction from initial and subsequent settings.
  • Tests

    • Added coverage for bridge replacement and synchronized UI settings.
    • Expanded automated validation for templates, including builds, architecture checks, linting, type-checking, and unit tests.
    • Added dedicated validation and testing for repository scripts.
    • Improved test fixture error reporting and type coverage.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pull request adds CI validation for repository templates, enables TypeScript checking and unit testing for scripts, strengthens JSDoc contracts and test fixtures, and updates template screens to resynchronize bridge-backed state and text direction when the bridge changes.

Changes

Tooling and validation

Layer / File(s) Summary
Script type contracts
tsconfig.scripts.json, package.json, scripts/check-test-dependency-versions.mjs, scripts/check-test-dependency-versions.test.mjs, scripts/ecosystem-version-policy.mjs, scripts/ecosystem-version-policy.test.mjs, scripts/verify-layered-configs.ts
Adds dedicated script type checking and testing. Narrows manifest, filesystem, dependency, and publication-policy JSDoc contracts.
Test-runner type contracts and fixtures
scripts/run-monorepo-unit-tests.mjs, scripts/run-monorepo-unit-tests.test.mjs, scripts/test-runner/*
Adds structural types, annotates runner fixtures, and replaces unchecked project lookups with mustFindProject.
Template validation workflow
.github/workflows/main.yml, .pre-commit-config.yaml, vitest.scripts.config.ts
Adds manifest-based validation for self-contained and composed overlay templates. Adds a scripts Vitest configuration and broadens JSON-hook exclusions to cover tsconfig*.json files.

React render synchronization

Layer / File(s) Summary
Template screen and bridge synchronization
template-mfe/src-app/mfe_packages/_blank-mfe/src/screens/home/*, template-mfe/src-app/mfe_packages/demo-mfe/src/screens/uikit/*, template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
Template screens read bridge properties during initialization and bridge replacement, maintain subscriptions, synchronize Shadow DOM direction, and add a targeted ESLint suppression.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HomeScreen
  participant UIKitElementsScreen
  participant Bridge
  participant ShadowDOM
  HomeScreen->>Bridge: read theme and language
  UIKitElementsScreen->>Bridge: read theme and language
  HomeScreen->>Bridge: subscribe to updates
  UIKitElementsScreen->>Bridge: subscribe to updates
  Bridge-->>HomeScreen: provide replacement bridge
  HomeScreen->>Bridge: resubscribe to replacement
  HomeScreen->>ShadowDOM: set rtl or ltr direction
  UIKitElementsScreen->>ShadowDOM: set rtl or ltr direction
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: gerabart

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the two main changes: template validation CI and scripts type-checking.
Docstring Coverage ✅ Passed Docstring coverage is 81.25% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/main.yml:
- Around line 80-86: Update the template-validate job to restrict its GitHub
token with job-level permissions allowing only contents: read, and configure the
actions/checkout step with persist-credentials disabled before
repository-controlled scripts run.
- Around line 88-98: Update the workflow around the “Enable Corepack” step to
avoid relying on Node.js 25’s removed bundled Corepack: remove the step if
validation only requires npm, or install and pin a userland Corepack package
before running corepack enable.

In
`@template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx`:
- Around line 52-59: Synchronize theme and language state whenever the bridge
identity changes instead of relying only on lazy useState initialization. Apply
this in HomeScreen.tsx (52-59), HelloWorldScreen.tsx (44-51),
CurrentThemeScreen.tsx (43-50), and UIKitElementsScreen.tsx (82-89), reading
each replacement bridge’s FRONTX_SHARED_PROPERTY_THEME and
FRONTX_SHARED_PROPERTY_LANGUAGE values while preserving the existing default
values.

In
`@template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/ProfileScreen.tsx`:
- Around line 64-67: Update ProfileScreen’s language direction handling so
root.host.dir is assigned inside a React effect keyed by language, covering both
the initial bridge value and later subscription updates. Preserve the existing
RTL language set and ensure initial ar, he, fa, or ur renders with rtl while
other languages remain ltr.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b003bd29-b9ce-4b0b-af73-da03fb373898

📥 Commits

Reviewing files that changed from the base of the PR and between 37b09ee and 7b355ba.

📒 Files selected for processing (38)
  • .github/workflows/main.yml
  • .pre-commit-config.yaml
  • package.json
  • scripts/check-test-dependency-versions.mjs
  • scripts/check-test-dependency-versions.test.mjs
  • scripts/ecosystem-version-policy.mjs
  • scripts/ecosystem-version-policy.test.mjs
  • scripts/run-monorepo-unit-tests.mjs
  • scripts/run-monorepo-unit-tests.test.mjs
  • scripts/test-runner/args.mjs
  • scripts/test-runner/common.mjs
  • scripts/test-runner/discovery.mjs
  • scripts/test-runner/orchestration.test.mjs
  • scripts/test-runner/spawning.mjs
  • scripts/verify-layered-configs.ts
  • template-standard/eslint.config.js
  • template-standard/packages/framework/__tests__/plugins/microfrontends/base-domains.test.ts
  • template-standard/packages/framework/__tests__/plugins/microfrontends/plugin.test.ts
  • template-standard/packages/framework/src/index.ts
  • template-standard/packages/framework/src/plugins/microfrontends/__tests__/sync-diff.test.ts
  • template-standard/packages/framework/src/plugins/microfrontends/actions.ts
  • template-standard/packages/framework/src/plugins/microfrontends/base-domains.ts
  • template-standard/packages/framework/src/plugins/microfrontends/index.ts
  • template-standard/packages/framework/src/testing/TestContainerProvider.ts
  • template-standard/packages/react/src/hooks/useApiStream.ts
  • template-standard/packages/react/src/hooks/useCanAccess.ts
  • template-standard/packages/react/src/hooks/useScreenTranslations.ts
  • template-standard/packages/react/src/mfe/components/ExtensionDomainSlot.tsx
  • template-standard/packages/react/src/queryClient.tsx
  • template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/components/ui/date-picker.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/helloworld/HelloWorldScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/ProfileScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/components/ProfileDetailsCard.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/theme/CurrentThemeScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/uikit/UIKitElementsScreen.tsx
  • tsconfig.scripts.json

Comment thread .github/workflows/main.yml
Comment thread .github/workflows/main.yml
Comment thread template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx Outdated
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 7b355ba to 66e49fa Compare July 30, 2026 02:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx (1)

72-103: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Initial RTL direction never applied for the lazily-read language. In each of these screens, dir on the shadow host is only set inside the language-change subscription callback; the language value read by the lazy useState initializer on first render never gets a corresponding dir update. A screen first mounted with ar/he/fa/ur stays LTR until the language actually changes. This was already flagged for ProfileScreen.tsx in a prior review round and remains unresolved there; UIKitElementsScreen.tsx in this same PR already fixes the gap by re-reading the property and applying dir once in the mount effect — the other three screens can follow that same approach.

  • template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx#L72-L103: apply the initial dir for the lazily-read language inside the mount effect, as done in UIKitElementsScreen.tsx.
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/helloworld/HelloWorldScreen.tsx#L56-L81: same initial-dir fix.
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/ProfileScreen.tsx#L119-L142: same initial-dir fix.
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/theme/CurrentThemeScreen.tsx#L55-L81: same initial-dir fix.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx`
around lines 72 - 103, Initial RTL direction is not applied when the lazily-read
language is already RTL. In HomeScreen.tsx lines 72-103, HelloWorldScreen.tsx
lines 56-81, ProfileScreen.tsx lines 119-142, and CurrentThemeScreen.tsx lines
55-81, update each mount effect to re-read the language property and apply the
shadow host’s dir using the existing RTL language handling, following
UIKitElementsScreen’s approach; retain the subscription updates and cleanup
unchanged.
♻️ Duplicate comments (1)
template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx (1)

52-59: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Lazy state initializer doesn't resync theme/language when bridge is replaced. All five screens read theme/language once via a lazy useState initializer and only subscribe for later property changes keyed on [bridge]; if the component ever receives a new bridge instance while staying mounted, the state keeps the previous bridge's values until that new bridge happens to fire a property-change event. This was already flagged for four of these files in a prior review round and remains unresolved; extending it to ProfileScreen.tsx, which has the identical pattern.

  • template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx#L52-L59: resync theme/language from the new bridge when bridge identity changes (e.g. via a render-time prevBridge check, mirroring the pattern already used in ProfileDetailsCard.tsx).
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/helloworld/HelloWorldScreen.tsx#L44-L51: same resync fix.
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/ProfileScreen.tsx#L56-L67: same resync fix.
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/theme/CurrentThemeScreen.tsx#L43-L50: same resync fix.
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/uikit/UIKitElementsScreen.tsx#L82-L89: same resync fix.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx`
around lines 52 - 59, Resync theme and language whenever the bridge instance
changes instead of relying only on the lazy useState initializers. Apply the
same bridge-identity change handling, mirroring ProfileDetailsCard, in
HomeScreen.tsx (52-59), HelloWorldScreen.tsx (44-51), ProfileScreen.tsx (56-67),
CurrentThemeScreen.tsx (43-50), and UIKitElementsScreen.tsx (82-89), preserving
event-based updates for the active bridge.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx`:
- Around line 72-103: Initial RTL direction is not applied when the lazily-read
language is already RTL. In HomeScreen.tsx lines 72-103, HelloWorldScreen.tsx
lines 56-81, ProfileScreen.tsx lines 119-142, and CurrentThemeScreen.tsx lines
55-81, update each mount effect to re-read the language property and apply the
shadow host’s dir using the existing RTL language handling, following
UIKitElementsScreen’s approach; retain the subscription updates and cleanup
unchanged.

---

Duplicate comments:
In
`@template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx`:
- Around line 52-59: Resync theme and language whenever the bridge instance
changes instead of relying only on the lazy useState initializers. Apply the
same bridge-identity change handling, mirroring ProfileDetailsCard, in
HomeScreen.tsx (52-59), HelloWorldScreen.tsx (44-51), ProfileScreen.tsx (56-67),
CurrentThemeScreen.tsx (43-50), and UIKitElementsScreen.tsx (82-89), preserving
event-based updates for the active bridge.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 104f3296-c186-438b-9629-c025aad108d7

📥 Commits

Reviewing files that changed from the base of the PR and between 7b355ba and 66e49fa.

📒 Files selected for processing (38)
  • .github/workflows/main.yml
  • .pre-commit-config.yaml
  • package.json
  • scripts/check-test-dependency-versions.mjs
  • scripts/check-test-dependency-versions.test.mjs
  • scripts/ecosystem-version-policy.mjs
  • scripts/ecosystem-version-policy.test.mjs
  • scripts/run-monorepo-unit-tests.mjs
  • scripts/run-monorepo-unit-tests.test.mjs
  • scripts/test-runner/args.mjs
  • scripts/test-runner/common.mjs
  • scripts/test-runner/discovery.mjs
  • scripts/test-runner/orchestration.test.mjs
  • scripts/test-runner/spawning.mjs
  • scripts/verify-layered-configs.ts
  • template-standard/eslint.config.js
  • template-standard/packages/framework/__tests__/plugins/microfrontends/base-domains.test.ts
  • template-standard/packages/framework/__tests__/plugins/microfrontends/plugin.test.ts
  • template-standard/packages/framework/src/index.ts
  • template-standard/packages/framework/src/plugins/microfrontends/__tests__/sync-diff.test.ts
  • template-standard/packages/framework/src/plugins/microfrontends/actions.ts
  • template-standard/packages/framework/src/plugins/microfrontends/base-domains.ts
  • template-standard/packages/framework/src/plugins/microfrontends/index.ts
  • template-standard/packages/framework/src/testing/TestContainerProvider.ts
  • template-standard/packages/react/src/hooks/useApiStream.ts
  • template-standard/packages/react/src/hooks/useCanAccess.ts
  • template-standard/packages/react/src/hooks/useScreenTranslations.ts
  • template-standard/packages/react/src/mfe/components/ExtensionDomainSlot.tsx
  • template-standard/packages/react/src/queryClient.tsx
  • template-standard/src-app/mfe_packages/_blank-mfe/src/screens/home/HomeScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/components/ui/date-picker.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/helloworld/HelloWorldScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/ProfileScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/profile/components/ProfileDetailsCard.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/theme/CurrentThemeScreen.tsx
  • template-standard/src-app/mfe_packages/demo-mfe/src/screens/uikit/UIKitElementsScreen.tsx
  • tsconfig.scripts.json
🚧 Files skipped from review as they are similar to previous changes (12)
  • template-standard/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
  • scripts/run-monorepo-unit-tests.mjs
  • scripts/ecosystem-version-policy.test.mjs
  • scripts/verify-layered-configs.ts
  • template-standard/packages/framework/src/plugins/microfrontends/actions.ts
  • scripts/test-runner/args.mjs
  • scripts/test-runner/spawning.mjs
  • scripts/test-runner/common.mjs
  • package.json
  • scripts/ecosystem-version-policy.mjs
  • scripts/test-runner/orchestration.test.mjs
  • scripts/test-runner/discovery.mjs

tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 30, 2026
… RTL direction, CI hardening

- MFE screens: re-read theme/language when the host swaps the bridge
  instance (lazy initializers only run on mount), via render-time
  adjustment; extracted readBridgeProperty helper.
- Set the Shadow-DOM host dir from an effect keyed by language instead
  of inside the subscription callback — the initial language (e.g. an
  MFE first rendered in ar/he/fa/ur) never fires a callback, so RTL was
  only applied after a language change.
- template-validate job: permissions contents:read and
  persist-credentials:false on checkout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp

Copy link
Copy Markdown
Contributor Author

Note for reviewers: review 4814781500 was generated against 66e49fa8, before the review-fix commit 27b79cd9 landed (CodeRabbit's re-review of that commit was rate-limited). Both of its findings — initial RTL direction for the lazily-read language, and theme/language resync on bridge replacement — are fixed in 27b79cd9 across all five MFE screens (via a dir effect keyed on [language] and a render-time prevBridge adjustment).

tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 30, 2026
… comment and marker fixes (review round 1 on constructorfabric#491)

- useApiStream: pin the new status contract with tests — first render
  reports 'connecting' when enabled (no idle flash), and disable→re-enable
  clears stale data and reconnects through 'connecting'.
- HomeScreen: test the bridge-swap path — current properties are re-read
  during render when the host swaps the bridge instance, old subscriptions
  torn down and re-registered on the new one.
- useCanAccess: hoist the no-auth-runtime denial to a module-level
  DENIED_NO_AUTH constant so the result keeps a stable identity across
  renders instead of allocating a fresh object each time.
- template-validate workflow: correct the file:-link depths in the comment
  (../packages/* from the template root, ../../../packages/* from nested
  template packages — not ../../packages/*).
- useCanAccess: add an inst-pending-effect marker region around the
  render-time re-pessimization so the relocated half of that instruction
  stays traced; cfs validate passes before and after.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 30, 2026
…ts/ type-checking (constructorfabric#483)

Part 1: new template-validate CI job builds the ecosystem packages the
templates file:-link, then globs template-*/ and runs each template's own
npm ci + build + arch:deps + lint + test:unit. Fixes the two breakages the
newly-enforced checks surfaced: template imports of FRONTX_ACTION_* re-pointed
from @gears-frontx/mfes to @gears-frontx/gts-plugin, and 15 react-hooks v6
lint errors fixed with behavior-preserving restructures.

Part 2: scripts/ is now type-checked via tsconfig.scripts.json wired into
type-check:all; the ~48-error backlog fixed with type-only changes. Also
widens the check-json pre-commit exclude to tsconfig*.json (JSONC).

Review round 1 (constructorfabric#491): tests pinning the useApiStream status contract and
the bridge-swap re-read path, stable DENIED_NO_AUTH identity in useCanAccess,
corrected file:-link depths in the workflow comment, and an added
inst-pending-effect marker region over the render-time re-pessimization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 09de4b7 to 4e8e694 Compare July 30, 2026 07:27
@gs-layer

Copy link
Copy Markdown
Contributor

Code review

Merge order: this PR must not be merged before #490.

#490 ("Split template-standard into template-shell + template-mfe") relocates the entire template-standard/ tree — 367 files to template-shell/, 341 to template-mfe/. 23 of the 38 files in this PR live under template-standard/**, and every one of them has a new home in #490:

  • template-standard/packages/** -> template-shell/packages/** (framework import re-routing, useApiStream, useCanAccess, useScreenTranslations, ExtensionDomainSlot, queryClient)
  • template-standard/src-app/mfe_packages/** -> template-mfe/src-app/mfe_packages/** (all 8 demo/blank MFE screen fixes, data-table, date-picker)

Merging this first would leave #490 to reconcile 23 modified files against a 733-file rename, which is exactly the case where rename detection is least reliable. Merging #490 first makes this PR the one that gets rebased, and it is the far smaller side of the two.

Direct file overlap between the two PRs is otherwise small and mechanical: .github/workflows/main.yml (#490 only edits one comment line — template-standard/ -> template-shell/ — and adds no job of its own), plus scripts/check-test-dependency-versions.mjs, scripts/run-monorepo-unit-tests.test.mjs and scripts/test-runner/discovery.mjs (a handful of lines each).

Worth noting the template-*/ glob in the new job is the right call here — the comment already anticipates the split via issue #470, and after #490 lands the loop picks up both template-shell/ and template-mfe/ with no workflow change:

# enforced only when someone runs them by hand — and they rot (#483). The
# glob loop deliberately avoids hardcoding template names so the job
# survives the planned template-shell/template-mfe split (#470).
template-validate:
name: Template Validate


Found 1 issue (minor):

  1. The eslint-disable justification overstates what the rule permits. It says the warning "only means this component is skipped by compilation, not that it misbehaves", but react-hooks/incompatible-library also covers passing values returned by the unanalyzable hook into other memoized components — and table is passed to <DataTablePagination table={table} /> further down the same file. Suggest narrowing the wording rather than the disable itself.

// eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table's useReactTable is not analyzable by the React Compiler; the warning only means this component is skipped by compilation, not that it misbehaves.
const internalTable = useReactTable({
data,

Otherwise clean. Checked: the FRONTX_ACTION_* re-routing covers exactly the 8 files that imported those constants directly from @gears-frontx/mfes (downstream consumers resolve through the framework re-export); the render-time state adjustments in useApiStream, useCanAccess and date-picker compare primitive fields and converge in one pass; the RTL dir effect fires on first commit because containerRef is attached in both the skeleton and the loaded branch; the scripts/ changes are type-only; no @cpt- marker was orphaned or unpaired.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Comment thread .github/workflows/main.yml
@itechmeat

Copy link
Copy Markdown
Contributor

@tscbmstubp Merge-order heads-up: this PR points the template's FRONTX_ACTION_* imports at @gears-frontx/gts-plugin, but the published gts-plugin@0.3.0-alpha.0 predates that move, and #492 pins the template to the registry - so whichever merges second goes red. Suggestion: merge #492 first, publish the next ecosystem alpha, then rebase this PR bumping the pins to it.

@gs-layer

Copy link
Copy Markdown
Contributor

Found while working on #489 — the new template-validate job has a guard that will behave differently than intended once the split lands, and the difference is about to become a red CI rather than a silent gap.

The guard skips half the split

for template in template-*/; do
  if [ ! -f "$template/package.json" ]; then
    continue
  fi

template-mfe/ is an add-only overlay: it has no root package.json by design (its frontx-template.json declares only src-app/mfe_packages/ and .frontx/ai/@gears-frontx/frontx-template-mfe/, and package.json is template-shell's exclusive subtree, so the mfe template cannot claim one). So as written, the loop silently skips it and validates template-shell only.

The job's own comment says the glob "deliberately avoids hardcoding template names so the job survives the planned template-shell/template-mfe split (#470)". The glob does survive — the guard one line below is what defeats it. Since this PR exists to fix "checks exist, nothing runs" (#483), it seemed worth flagging that the same pattern reappears on the other half.

template-shell is genuinely covered: it has every script the job calls (arch:deps, lint, test:unit, build:package, build:packages).

And it is about to flip to a hard failure

Work on #489 adds a monorepo-only build harness at template-mfe/package.json (commit b63faffe on feature/489-template-mfe-harness, not yet a PR). Without it the MFE packages resolve nothing inside the monorepo — npm install exits 0 while require.resolve('@gears-frontx/frontx-template-shell/build/mf-gts') throws MODULE_NOT_FOUND. The harness is deliberately undeclared in the manifest, so it never ships into a seeded project; it exists purely so this repo can build and type-check those packages.

Side effect: the guard stops skipping template-mfe, which is what you want — but the job then calls arch:deps, lint and test:unit on it without --if-present (only the two build steps carry that flag), and the harness deliberately carries no scripts. That is a failing job the first time both changes meet.

Two ways out, and it seems better to pick one before the merge rather than discover it in CI:

  1. add --if-present to the three unflagged calls, matching the build steps; or
  2. decide the harness should carry those three scripts, in which case normalize MFE file: dependencies and undeclared mf-gts coupling in template-mfe #489 adds them.

Preference is (1) — it keeps the harness minimal and version-free, which is the property that stops it drifting out of step with packages/*/package.json. Happy to go with (2) if you would rather the job stay strict.

Minor, same job

The ecosystem-build step is justified by:

Templates link the ecosystem packages (mfes, gts-plugin, api) via file: paths into this repo's packages/ … npm installs those as symlinks, so the ecosystem dist/ must exist before the template's own packages can build against them.

#492 replaces those file: paths with exact registry pins, after which nothing is symlinked and the step becomes a slow no-op with a comment describing something that no longer happens. Nothing breaks — just worth a follow-up touch depending on merge order.

Also unrelated to this PR but adjacent: the pre-existing per-MFE loop at .github/workflows/main.yml:41 iterates src/mfe_packages/*/, a path that exists nowhere in this repo (the real one is src-app/mfe_packages/*). It has been running on nothing — the same class this PR is fixing, if you want to sweep it here.

tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 31, 2026
Review follow-ups on constructorfabric#491.

1. scripts/ has 183 vitest tests across 4 files that nothing ran. test:unit
   fans out to the npm workspaces via run-monorepo-unit-tests.mjs and scripts/
   is not a workspace, so no project ever collected them — including the tests
   this very PR adds to three of those files. Added vitest.scripts.config.ts
   and chained test:unit:scripts into test:unit, so CI picks it up with no
   workflow change. All 183 pass as-is.

2. Removed the dead "Install MFE dependencies" step. It looped over
   src/mfe_packages/*/, a path that has not existed since the MFEs moved under
   the templates, and fed a root type-check:mfe script that no longer exists.
   Deleted rather than repointed — the MFE packages are template content and
   template-validate now installs and checks them. (gs-layer)

3. template-validate now classifies templates by what their manifest claims
   rather than by a -f package.json test. constructorfabric#489 adds a root package.json to
   template-mfe as a monorepo-only build harness, deliberately undeclared so it
   never ships; the disk test would route the overlay down the self-contained
   path and fail on scripts a harness has no reason to define. Verified both
   ways: with a stub harness in place the old guard calls template-mfe
   self-contained, the manifest classifier still calls it an overlay.

   This is gs-layer's option (1) problem solved without option (1)'s cost —
   no --if-present on arch:deps/lint/test:unit, so a real template that loses
   a script still fails loudly instead of going quietly unchecked.

4. Added `npm run type-check` to both template paths — it was the one script
   the job left orphaned, which itechmeat flagged as contradicting the PR's own
   premise. It ends in type-check:mfe, vacuous standalone and real in the
   composed run.

5. Comment corrections: the data-table eslint-disable no longer claims the rule
   only means "skipped by compilation" — it also covers passing `table` to
   DataTablePagination, now stated with why that is accepted (gs-layer); and
   UIKitElementsScreen no longer says direction comes from useScreenTranslations
   when the effect below owns it (itechmeat).

Verified: root type-check:all, lint, test:unit (now incl. 183 scripts tests),
arch:check; and the full template-validate job step by step — classify, the
self-contained run, and the composed run (4 MFEs type-checked, both
test-bearing MFEs run).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 31, 2026
The last two orphaned template scripts itechmeat asked about on constructorfabric#491. Both
template paths now run `npm run build` instead of just build:package plus
build:packages, which additionally chains build:mfes, generate:mfe-manifests
and vite build — none of which anything in CI ran. It runs first so the later
checks see the generated manifests.

Not a scope cut after all: I had assumed a full vite build was too expensive to
add, and measuring said otherwise — 1:12 for the standalone template, 2:03 for
the composed one, and both were already green.

Standalone degrades cleanly (build-mfes.ts and generate-mfe-manifests.ts both
report zero packages and skip); the composed run builds all four MFEs and the
host bundle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/main.yml (1)

10-32: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Restrict credentials on the validate job too.

The template-validate job now sets permissions: contents: read and persist-credentials: false after a prior review flagged it. The sibling validate job at Line 10 still has no permissions: block, and its checkout at Line 18-19 does not set persist-credentials: false, even though it also runs npm ci, builds, lint, and npm audit immediately after checkout. The static analysis hint below still flags this range.

🔒 Proposed fix
   validate:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read

     strategy:
       matrix:
         node-version: [24.14.x, 25.x]

     steps:
     - name: Checkout code
       uses: actions/checkout@v5
+      with:
+        persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/main.yml around lines 10 - 32, Restrict credentials for
the validate job by adding a read-only contents permissions block and configure
its actions/checkout step with persist-credentials disabled. Update the validate
job and its Checkout code step only; leave the existing Node setup and
dependency installation flow unchanged.

Source: Linters/SAST tools

🧹 Nitpick comments (2)
template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx (1)

60-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the suppression comment focused on its actual scope.

eslint-disable-next-line applies only to the useReactTable line. It does not suppress a separate diagnostic for passing table to DataTablePagination. Describe the useReactTable incompatibility here, and add a separate targeted suppression only if ESLint reports the child-prop diagnostic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx`
at line 60, Update the eslint suppression comment immediately before
useReactTable to describe only TanStack Table’s incompatibility with the React
Compiler. Remove the claims about passing table to DataTablePagination and
memoization; add a separate targeted suppression at the child prop only if
ESLint reports that diagnostic.
vitest.scripts.config.ts (1)

1-15: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Wire the scripts Vitest config into shared project settings.

test:unit runs test:unit:scripts, so the repo-level suites are collected. This config still uses a bare defineConfig, so it does not inherit root/shared Vitest settings such as aliases, coverage thresholds, or setup files. Update it to merge or extend the shared/root config and use a shared coverage threshold if it is currently project-scoped.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vitest.scripts.config.ts` around lines 1 - 15, Update the Vitest
configuration exported by defineConfig to extend the repository’s shared/root
Vitest settings, preserving the scripts-specific name, include, exclude, and
environment options. Reuse the shared coverage threshold configuration rather
than defining a separate project-scoped threshold, and retain inherited aliases
and setup files.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/main.yml:
- Around line 202-237: Update the overlay copy logic in the loop over
OVERLAY_TEMPLATES and exclusiveSubtrees so existing destination directories are
merged rather than nested. Preserve the current subtree validation and
destination creation, but copy the contents of each source subtree into
"$shell/${subtree%/}" instead of copying the directory itself, ensuring existing
paths such as src-app/mfe_packages receive the overlay packages at the expected
depth.

---

Outside diff comments:
In @.github/workflows/main.yml:
- Around line 10-32: Restrict credentials for the validate job by adding a
read-only contents permissions block and configure its actions/checkout step
with persist-credentials disabled. Update the validate job and its Checkout code
step only; leave the existing Node setup and dependency installation flow
unchanged.

---

Nitpick comments:
In
`@template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx`:
- Line 60: Update the eslint suppression comment immediately before
useReactTable to describe only TanStack Table’s incompatibility with the React
Compiler. Remove the claims about passing table to DataTablePagination and
memoization; add a separate targeted suppression at the child prop only if
ESLint reports that diagnostic.

In `@vitest.scripts.config.ts`:
- Around line 1-15: Update the Vitest configuration exported by defineConfig to
extend the repository’s shared/root Vitest settings, preserving the
scripts-specific name, include, exclude, and environment options. Reuse the
shared coverage threshold configuration rather than defining a separate
project-scoped threshold, and retain inherited aliases and setup files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c4b6636-c75d-4a88-b4b2-69263a2e8bfe

📥 Commits

Reviewing files that changed from the base of the PR and between abcc6d2 and 7b3d5bc.

📒 Files selected for processing (5)
  • .github/workflows/main.yml
  • package.json
  • template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
  • template-mfe/src-app/mfe_packages/demo-mfe/src/screens/uikit/UIKitElementsScreen.tsx
  • vitest.scripts.config.ts

Comment thread .github/workflows/main.yml Outdated
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 7b3d5bc to 9a0d5ae Compare July 31, 2026 06:21
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 31, 2026
…tructorfabric#483)

Several checks in this repo existed but nothing ran them. Each is a script or
suite someone wrote deliberately, wired to nothing, quietly rotting.

Templates. Each template tree carries its own arch:deps / lint / test:unit /
type-check / build, and no workflow entered those trees, so they were enforced
only by hand. The new template-validate job covers both halves of the constructorfabric#470
split, classifying templates by what their manifests claim rather than by what
sits on disk:

  - self-contained (template-shell, which declares package.json among its
    ownership boundaries) is validated standalone;
  - add-only overlays (template-mfe) are composed onto the shell the way
    `frontx add` does and validated as the union. They cannot be checked in
    place: their file:../../../packages/* links resolve to a template-mfe/
    packages/ that does not exist, their vitest configs import the shell's
    src-app/vitest.mfe.base, and template-mfe has no eslint config of its own.

Reading manifests rather than testing for a file on disk matters because constructorfabric#489
adds a root package.json to template-mfe as a monorepo-only build harness,
deliberately undeclared so it never ships into a seeded project. A -f test
would route the overlay down the self-contained path and fail on scripts a
harness has no reason to define. The alternative — relaxing arch:deps / lint /
test:unit to --if-present — would let a real template lose a script and go
quietly unchecked, which is the failure this job exists to prevent.

Composition subtrees come from each overlay's own exclusiveSubtrees, mirroring
the assembler (packages/cli/src/scaffold/assembler.ts). Every check is a silent
no-op if the overlay fails to land, so the step asserts a non-zero MFE package
count before running anything.

Newly-enforced template lint surfaced 15 react-hooks v6 errors, fixed here with
behaviour-preserving restructures across the MFE screens and the react package.

scripts/. Two separate gaps. The tooling is now type-checked via
tsconfig.scripts.json wired into type-check:all — it runs under tsx, which
strips types without checking them, so a type error in an architecture guard
surfaced only as a runtime failure; the ~48-error backlog is fixed with
type-only changes. Separately, scripts/ ships 183 vitest tests across 4 files
that no project collected, because test:unit fans out to the npm workspaces and
scripts/ is not one. vitest.scripts.config.ts gives them a home, chained into
test:unit; all 183 pass unchanged.

Also removed the "Install MFE dependencies" step, which looped over
src/mfe_packages/*/ — a path gone since the MFEs moved under the templates —
feeding a root type-check:mfe script that no longer exists. And widened the
check-json pre-commit exclude to tsconfig*.json, which is JSONC.

Review rounds on constructorfabric#491: tests pinning the useApiStream status contract and the
bridge-swap re-read path; stable DENIED_NO_AUTH identity in useCanAccess; an
inst-pending-effect marker over the render-time re-pessimization; the template's
own type-check and full build (build:mfes, generate:mfe-manifests, vite build)
added to both paths after measuring the cost at 1:12 standalone and 2:03
composed; and corrected justifications on the data-table eslint-disable and the
UIKitElementsScreen direction comment.

Follow-up on the bridge/RTL logic duplicated across five screens: constructorfabric#502.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 9a0d5ae to d059ea9 Compare July 31, 2026 06:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/main.yml:
- Around line 213-215: Update the exclusiveSubtrees validation loop around the
subtree directory check so a declared subtree missing under the current overlay
causes the workflow to fail instead of being skipped. Preserve skipping blank
entries, but replace the silent continue for absent "$overlay/$subtree"
directories with the workflow’s established failure mechanism before processing
subsequent validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3e741464-1da8-44cc-a669-783df41d80e8

📥 Commits

Reviewing files that changed from the base of the PR and between 7b3d5bc and 9a0d5ae.

📒 Files selected for processing (5)
  • .github/workflows/main.yml
  • package.json
  • template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
  • template-mfe/src-app/mfe_packages/demo-mfe/src/screens/uikit/UIKitElementsScreen.tsx
  • vitest.scripts.config.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • template-mfe/src-app/mfe_packages/demo-mfe/src/components/ui/data-table/data-table.tsx
  • vitest.scripts.config.ts
  • package.json
  • template-mfe/src-app/mfe_packages/demo-mfe/src/screens/uikit/UIKitElementsScreen.tsx

Comment thread .github/workflows/main.yml Outdated
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Jul 31, 2026
…tructorfabric#483)

Several checks in this repo existed but nothing ran them. Each is a script or
suite someone wrote deliberately, wired to nothing, quietly rotting.

Templates. Each template tree carries its own arch:deps / lint / test:unit /
type-check / build, and no workflow entered those trees, so they were enforced
only by hand. The new template-validate job covers both halves of the constructorfabric#470
split, classifying templates by what their manifests claim rather than by what
sits on disk:

  - self-contained (template-shell, which declares package.json among its
    ownership boundaries) is validated standalone;
  - add-only overlays (template-mfe) are composed onto the shell the way
    `frontx add` does and validated as the union. They cannot be checked in
    place: their file:../../../packages/* links resolve to a template-mfe/
    packages/ that does not exist, their vitest configs import the shell's
    src-app/vitest.mfe.base, and template-mfe has no eslint config of its own.

Reading manifests rather than testing for a file on disk matters because constructorfabric#489
adds a root package.json to template-mfe as a monorepo-only build harness,
deliberately undeclared so it never ships into a seeded project. A -f test
would route the overlay down the self-contained path and fail on scripts a
harness has no reason to define. The alternative — relaxing arch:deps / lint /
test:unit to --if-present — would let a real template lose a script and go
quietly unchecked, which is the failure this job exists to prevent.

Composition subtrees come from each overlay's own exclusiveSubtrees, mirroring
the assembler (packages/cli/src/scaffold/assembler.ts). Every check is a silent
no-op if the overlay fails to land, so the step asserts a non-zero MFE package
count before running anything.

Newly-enforced template lint surfaced 15 react-hooks v6 errors, fixed here with
behaviour-preserving restructures across the MFE screens and the react package.

scripts/. Two separate gaps. The tooling is now type-checked via
tsconfig.scripts.json wired into type-check:all — it runs under tsx, which
strips types without checking them, so a type error in an architecture guard
surfaced only as a runtime failure; the ~48-error backlog is fixed with
type-only changes. Separately, scripts/ ships 183 vitest tests across 4 files
that no project collected, because test:unit fans out to the npm workspaces and
scripts/ is not one. vitest.scripts.config.ts gives them a home, chained into
test:unit; all 183 pass unchanged.

Also removed the "Install MFE dependencies" step, which looped over
src/mfe_packages/*/ — a path gone since the MFEs moved under the templates —
feeding a root type-check:mfe script that no longer exists. And widened the
check-json pre-commit exclude to tsconfig*.json, which is JSONC.

Review rounds on constructorfabric#491: tests pinning the useApiStream status contract and the
bridge-swap re-read path; stable DENIED_NO_AUTH identity in useCanAccess; an
inst-pending-effect marker over the render-time re-pessimization; the template's
own type-check and full build (build:mfes, generate:mfe-manifests, vite build)
added to both paths after measuring the cost at 1:12 standalone and 2:03
composed; and corrected justifications on the data-table eslint-disable and the
UIKitElementsScreen direction comment.

Follow-up on the bridge/RTL logic duplicated across five screens: constructorfabric#502.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from d059ea9 to 29e8bc3 Compare July 31, 2026 06:52
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Aug 7, 2026
…ryFactory exists on the registry

6a50d21 renamed packages/mfes's public factory export from
DefaultMfeRegistryFactory to createMfeRegistryFactory (keeping the
concrete factory off the public surface per ADR-0003) but never bumped
the package version, so the published 0.3.0-alpha.1 tarball still only
has the old export. template-shell/packages/framework/src/mfe/registry.ts
already imports the new name, so any template build that installs the
pinned registry version (not this repo's local workspace source) fails
with "has no exported member named 'createMfeRegistryFactory'" — caught
by the Template Validate job PR constructorfabric#491 wires up.

gts-plugin exactly pins @gears-frontx/mfes and is force-sorted right
after it in the publish workflow, so it bumps in lockstep here too,
mirroring the original 0.3.0-alpha.1 pair (constructorfabric#492).

Every site pinning the pair to the exact registry version moves onto
0.3.0-alpha.2 in the same commit, keeping policy:template-pin-drift
green: template-shell/package.json,
template-shell/packages/framework/package.json, and the three
template-mfe fixture manifests that declare the pair directly
(_blank-mfe, widgets-fixture-a, widgets-fixture-b).

Also bumps template-shell's own version (package.json +
frontx-template.json) since detect-template in publish-packages.yml
only builds/validates a template when its own version changes between
pushes — and cascades that bump into the four template-mfe fixtures
(_blank-mfe, demo-mfe, widgets-fixture-a, widgets-fixture-b) that pin
@gears-frontx/frontx-template-shell exactly, which would otherwise
drift the moment the shell's version moves.

NOT included: template-shell/package-lock.json. Its node_modules
entries for @gears-frontx/mfes and @gears-frontx/gts-plugin carry a
real resolved tarball URL and integrity hash that only exist once
0.3.0-alpha.2 is actually published — hand-editing them now would
either fabricate a wrong integrity (npm ci refuses on mismatch) or
leave stale alpha.1 data that contradicts the manifest (npm ci refuses
on drift either way). Regenerate via a real `npm install` against the
live registry once this merges and publishes (the same two-merge
sequence constructorfabric#485/constructorfabric#492 needed), then commit the result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
gs-layer added a commit to gs-layer/gears-frontx that referenced this pull request Aug 10, 2026
…torfabric#531)

.github/workflows/main.yml: drop the "Install MFE dependencies" step —
its src/mfe_packages/*/ glob predates constructorfabric#470's split and never matches;
root package.json only workspaces packages/* and internal/*, so the
step never fed any downstream root check anyway. MFE package deps are
installed by each template's own npm ci inside the template-validate
job (constructorfabric#491), which already covers this.

knip.json: repoint the root workspace's entry/project/ignore globs from
the pre-split src/ tree at scripts/**, the only thing knip's root scope
still owns; drop ignoreDependencies and ignoreIssues entries that named
now-removed src/ paths. Clears arch:check's three "no matches"/"remove
from ignoreDependencies" configuration hints.

Signed-off-by: G S <grigoriis.dev@gmail.com>
GeraBart pushed a commit that referenced this pull request Aug 10, 2026
…ryFactory exists on the registry

6a50d21 renamed packages/mfes's public factory export from
DefaultMfeRegistryFactory to createMfeRegistryFactory (keeping the
concrete factory off the public surface per ADR-0003) but never bumped
the package version, so the published 0.3.0-alpha.1 tarball still only
has the old export. template-shell/packages/framework/src/mfe/registry.ts
already imports the new name, so any template build that installs the
pinned registry version (not this repo's local workspace source) fails
with "has no exported member named 'createMfeRegistryFactory'" — caught
by the Template Validate job PR #491 wires up.

gts-plugin exactly pins @gears-frontx/mfes and is force-sorted right
after it in the publish workflow, so it bumps in lockstep here too,
mirroring the original 0.3.0-alpha.1 pair (#492).

Every site pinning the pair to the exact registry version moves onto
0.3.0-alpha.2 in the same commit, keeping policy:template-pin-drift
green: template-shell/package.json,
template-shell/packages/framework/package.json, and the three
template-mfe fixture manifests that declare the pair directly
(_blank-mfe, widgets-fixture-a, widgets-fixture-b).

Also bumps template-shell's own version (package.json +
frontx-template.json) since detect-template in publish-packages.yml
only builds/validates a template when its own version changes between
pushes — and cascades that bump into the four template-mfe fixtures
(_blank-mfe, demo-mfe, widgets-fixture-a, widgets-fixture-b) that pin
@gears-frontx/frontx-template-shell exactly, which would otherwise
drift the moment the shell's version moves.

NOT included: template-shell/package-lock.json. Its node_modules
entries for @gears-frontx/mfes and @gears-frontx/gts-plugin carry a
real resolved tarball URL and integrity hash that only exist once
0.3.0-alpha.2 is actually published — hand-editing them now would
either fabricate a wrong integrity (npm ci refuses on mismatch) or
leave stale alpha.1 data that contradicts the manifest (npm ci refuses
on drift either way). Regenerate via a real `npm install` against the
live registry once this merges and publishes (the same two-merge
sequence #485/#492 needed), then commit the result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Aug 10, 2026
…ts/ type-checking (constructorfabric#483)

Adds two CI gates that previously ran only by hand:

- `template-validate` job: validates template-shell standalone and
  template-mfe composed onto template-shell (build, type-check,
  arch:deps, lint, test:unit for both), classifying templates by what
  their manifest CLAIMS rather than disk presence.
- `type-check:scripts` (tsconfig.scripts.json), wired into
  `type-check:all` and CI's TypeScript validation step, so `scripts/`
  gets the same type coverage as the rest of the monorepo.

Includes fixes from @itechmeat's review of constructorfabric#491:
- Structural FileSystemLike typing for link-template-ecosystem.mjs's
  injected fs, needed once type-check:scripts started covering it —
  re-ported onto constructorfabric#518's rewrite of the script during rebase. The gate
  paid for itself immediately: it caught the rewrite's rollback message
  printing a literal "undefined" recovery line when every package was
  restored (recoveryLine assigned in two of three branches), fixed here.
- JSDoc annotations for constructorfabric#493's new scripts (validate-templates,
  template-discovery, template-ecosystem-packages, template-pin-drift)
  and their tests, which predate the type-check:scripts gate.
- template-shell's ecosystem pins moved to 0.3.0-alpha.1 (the
  FRONTX_ACTION_*/DomainContext.typeSystem move constructorfabric#485 recorded), and a
  lockfile self-link entry corrupted independently in develop, fixed.
  Also synced the lockfile to develop's api alpha.1 pin bump (309d77f
  updated package.json only — nothing on develop runs `npm ci` inside
  the template, so the desync was green there and red on this job's
  first standalone install).
- Classify/compose steps refuse a non-empty ownershipBoundaries.sharedFiles
  instead of half-implementing the merge-strategy contract; the overlay
  MFE-package count is per-overlay (from the manifest's own subtree paths)
  instead of one aggregate that could mask a broken overlay behind a
  working one; the composed lockfile cleanup reads the same subtree paths
  instead of hardcoding mfe_packages.
- Workflow-level `permissions: contents: read` and
  `persist-credentials: false` on every checkout, not just
  template-validate's.
- template-validate drops `npm run build:packages`: with the pins on
  registry tarballs, nothing in the job reads the workspace packages'
  dist/ output.
- useCanAccess.ts/useScreenTranslations.ts @cpt- marker regions no
  longer duplicate or drop the behavior they're supposed to trace;
  inst-pending-effect marks the one render-time re-pessimize site.
- Shared DirEntryLike typedef (scripts/fs-types.mjs) instead of two
  independently-drifting copies.
- Comment sweep: change-history framing ("used to", "previously",
  constructorfabric#485's alpha.0-to-alpha.1 story told twice) rewritten as present-tense
  descriptions of the code that is there.

- template-shell's .dependency-cruiser.cjs matches node_modules at any
  depth in doNotFollow, not just the root: the composed tree nests a
  node_modules under each overlaid src-app/mfe_packages/* workspace, and
  the anchored pattern let dependency-cruiser traverse the entire
  installed dependency universe — OOM at the default heap. Standalone
  370 modules, composed 532, both green.

Version bumps (alpha) for the packages this change touches:
frontx-template-shell 0.1.0-alpha.2 (develop took alpha.1 for the constructorfabric#476
pin fix); framework, react, blank-mfe, demo-mfe 0.2.0-alpha.1.

Deferred to follow-ups, tracked in constructorfabric#502, constructorfabric#515, constructorfabric#516: the RTL/bridge-resync
duplication across five MFE screens, a shared useLatest helper for three
deps-less ref-write effects (blocked on eslint-plugin-react-hooks not
recognizing custom-hook-returned refs), and documenting useApiStream's
status lifecycle against architecture/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 17ec1d5 to da38bfd Compare August 10, 2026 07:03
GeraBart pushed a commit that referenced this pull request Aug 10, 2026
… deferred

#535 bumped @gears-frontx/mfes and @gears-frontx/gts-plugin to
0.3.0-alpha.2 (and template-shell's own version to 0.1.0-alpha.2)
across the template manifests, but deliberately left both template
lockfiles untouched: the alpha.2 tarball URL and integrity hash did
not exist until that PR merged and published. Its commit message asks
for exactly this follow-up. Until it lands, npm ci in template-shell
fails with 'lock file's @gears-frontx/gts-plugin@0.3.0-alpha.1 does
not satisfy 0.3.0-alpha.2', which is what currently fails the
Template Validate job on PR #491's rebase.

Rather than regenerating with npm install (which drops the file:
self-link entry — the trap bab4fec documented), this patches the
lockfiles surgically:

- template-shell/package-lock.json: the mfes and gts-plugin
  node_modules entries get the alpha.2 version, resolved URL, and the
  registry's real integrity hashes (from npm view dist.integrity),
  plus the two manifest-mirror blocks (root and packages/framework).
- template-mfe/package-lock.json: mirror-only — mfes/gts-plugin pins
  to 0.3.0-alpha.2 and frontx-template-shell to 0.1.0-alpha.2 in the
  four fixture mirror blocks; the packages themselves resolve to
  local links there.

Verified: rm -rf node_modules && npm ci exits 0 in template-shell
with the self-link intact and alpha.2 installed; npm ci --dry-run
passes in template-mfe; npm run build -w packages/framework (the DTS
build Template Validate died on) passes; policy:version-check and
policy:template-pin-drift both pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Aug 10, 2026
…ts/ type-checking (constructorfabric#483)

Adds two CI gates that previously ran only by hand:

- `template-validate` job: validates template-shell standalone and
  template-mfe composed onto template-shell (build, type-check,
  arch:deps, lint, test:unit for both), classifying templates by what
  their manifest CLAIMS rather than disk presence.
- `type-check:scripts` (tsconfig.scripts.json), wired into
  `type-check:all` and CI's TypeScript validation step, so `scripts/`
  gets the same type coverage as the rest of the monorepo.

Includes fixes from @itechmeat's review of constructorfabric#491:
- Structural FileSystemLike typing for link-template-ecosystem.mjs's
  injected fs, needed once type-check:scripts started covering it —
  re-ported onto constructorfabric#518's rewrite of the script during rebase. The gate
  paid for itself immediately: it caught the rewrite's rollback message
  printing a literal "undefined" recovery line when every package was
  restored (recoveryLine assigned in two of three branches), fixed here.
- JSDoc annotations for constructorfabric#493's new scripts (validate-templates,
  template-discovery, template-ecosystem-packages, template-pin-drift)
  and their tests, which predate the type-check:scripts gate.
- template-shell's ecosystem pins moved to 0.3.0-alpha.1 (the
  FRONTX_ACTION_*/DomainContext.typeSystem move constructorfabric#485 recorded), and a
  lockfile self-link entry corrupted independently in develop, fixed.
  Also synced the lockfile to develop's api alpha.1 pin bump (309d77f
  updated package.json only — nothing on develop runs `npm ci` inside
  the template, so the desync was green there and red on this job's
  first standalone install).
- Classify/compose steps refuse a non-empty ownershipBoundaries.sharedFiles
  instead of half-implementing the merge-strategy contract; the overlay
  MFE-package count is per-overlay (from the manifest's own subtree paths)
  instead of one aggregate that could mask a broken overlay behind a
  working one; the composed lockfile cleanup reads the same subtree paths
  instead of hardcoding mfe_packages.
- Workflow-level `permissions: contents: read` and
  `persist-credentials: false` on every checkout, not just
  template-validate's.
- template-validate drops `npm run build:packages`: with the pins on
  registry tarballs, nothing in the job reads the workspace packages'
  dist/ output.
- useCanAccess.ts/useScreenTranslations.ts @cpt- marker regions no
  longer duplicate or drop the behavior they're supposed to trace;
  inst-pending-effect marks the one render-time re-pessimize site.
- Shared DirEntryLike typedef (scripts/fs-types.mjs) instead of two
  independently-drifting copies.
- Comment sweep: change-history framing ("used to", "previously",
  constructorfabric#485's alpha.0-to-alpha.1 story told twice) rewritten as present-tense
  descriptions of the code that is there.

- template-shell's .dependency-cruiser.cjs matches node_modules at any
  depth in doNotFollow, not just the root: the composed tree nests a
  node_modules under each overlaid src-app/mfe_packages/* workspace, and
  the anchored pattern let dependency-cruiser traverse the entire
  installed dependency universe — OOM at the default heap. Standalone
  370 modules, composed 532, both green.

Version bumps (alpha) for the packages this change touches:
frontx-template-shell 0.1.0-alpha.2 (develop took alpha.1 for the constructorfabric#476
pin fix); framework, react, blank-mfe, demo-mfe 0.2.0-alpha.1.

Deferred to follow-ups, tracked in constructorfabric#502, constructorfabric#515, constructorfabric#516: the RTL/bridge-resync
duplication across five MFE screens, a shared useLatest helper for three
deps-less ref-write effects (blocked on eslint-plugin-react-hooks not
recognizing custom-hook-returned refs), and documenting useApiStream's
status lifecycle against architecture/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from da38bfd to 33daf83 Compare August 10, 2026 07:22
gs-layer added a commit to gs-layer/gears-frontx that referenced this pull request Aug 10, 2026
…torfabric#531)

.github/workflows/main.yml: drop the "Install MFE dependencies" step.
Its src/mfe_packages/*/ glob predates constructorfabric#470's split and matches nothing
at base or head. Independent of the dead glob: the type-check:mfe
script the deleted comment named lives only in template-shell's own
package.json now, not root's, and neither template-mfe/src-app/
mfe_packages/* nor template-shell/src-app/mfe_packages/* carries a
per-package package-lock.json — so even a correctly repointed loop's
`-f package-lock.json` guard would skip every directory. Nothing in
the root `validate` job installs or consumes MFE package deps today,
so deleting is safe on develop as it stands, independent of constructorfabric#491's
still-unmerged template-validate job (once merged, that job's
per-template npm ci is where MFE deps actually get installed).

knip.json: repoint the root workspace's entry/project/ignore globs from
the pre-split src/ tree at scripts/**, the only thing knip's root scope
still owns. Also drop ignoreDependencies (@types/*,
@gears-frontx/depcruise-config/*) and the ignoreIssues entry for
*Screen.tsx, plus three dead global ignore globs (eslint-plugin-local/**,
vite.config.ts, .eslintrc.cjs) naming removed src/-era paths. Verified
no regression: `npm run arch:unused`'s finding set is byte-identical
before and after — dropping ignoreDependencies does not surface
@gears-frontx/depcruise-config (knip's dependency-cruiser plugin
already resolves packages/api/.dependency-cruiser.cjs's require() of
it) or @types/lodash (unused either way) as new findings. Clears
arch:check's three "no matches"/"remove from ignoreDependencies"
configuration hints.

Signed-off-by: G S <grigoriis.dev@gmail.com>
@gs-layer

Copy link
Copy Markdown
Contributor

Merge-order note from review: this PR should merge only after #558, then be rebased/rechecked. The current merge-ref Template Validate job fails in the composed template-shell + template-mfe tree while type-checking _blank-mfe (src/components/ui/button.tsx React type errors). That failure is in the same template-mfe React 19.2/type-alignment surface that #558 addresses, so merging #491 first would land the new validation job red on the current composition.

@gs-layer

gs-layer commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Merge-order note from review: this PR should also merge only after #521, then be rebased/rechecked. #521 is the current code-altitude documentation for useApiStream status lifecycle, while #491 changes the same hook observable status behavior: initial enabled render becomes connecting, re-enable clears stale data before paint, and disabled status is derived as idle. If #491 lands before #521, #521 can reintroduce documentation for the pre-#491 lifecycle or create a stale conflict resolution path. Merge #521 first, then have #491 carry the runtime rewrite plus matching docs/tests on top.

tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Aug 12, 2026
…int rules

Two develop-side changes broke template-mfe under the composed template
validation that PR constructorfabric#491 wires up (nothing on develop runs it, so both
drifted silently):

- 3ea1ee9 moved template-shell to @types/react 19.2.18 (useEffectEvent
  needs it) while the four MFE fixture manifests still pinned 19.0.8.
  Composed, the tree installs both copies and _blank-mfe's type-check
  dies in button.tsx with TS2786/TS2322 (Radix Slot typed against one
  copy, the component's ref against the other). All four manifests and
  the template-mfe lockfile (mirrors + hoisted entry, registry
  integrity) move to 19.2.18.

- The composed eslint run resolves eslint-plugin-react-hooks 7.1.1
  upward from the repo root, and its recommended set flags the MFE
  screens' bridge-resync pattern (set-state-in-effect) — the same
  violations constructorfabric#491 fixed in the shell's own hooks and deferred for the
  five MFE screens. Fixed with the same patterns the shell uses:

  - HomeScreen (_blank), HelloWorldScreen, CurrentThemeScreen,
    ProfileScreen, UIKitElementsScreen: initial theme/language read in
    lazy useState initializers (first paint now reflects the host's
    shared properties) with the effect reduced to subscriptions.
  - ProfileDetailsCard, date-picker: 'adjusting state during render'
    (react.dev) with a prev-key comparison instead of a sync-with-props
    effect.
  - data-table: targeted eslint-disable for
    react-hooks/incompatible-library — TanStack Table's useReactTable
    is documented as uncompilable, and the composed lint runs with
    --max-warnings 0.

CodeRabbit's review then flagged that the four bridge-synced screens
never apply the text direction for the initial language — only the
subscription callbacks set dir, so an initially-RTL host renders LTR
until the next language event. That gap predates this PR, but with
language now correct from the first render the fix is natural: each
screen gets one effect keyed on the language state that applies the
shadow-host dir after commit, covering the initial value and every
later change. That effect subsumes the per-callback dir duplication
(callbacks shrink to setLanguage) and collapses UIKitElementsScreen's
separate initial-dir bridge read into the same shared shape.

Verified on a locally composed shell+overlay tree (the same copy,
lockfile-drop, npm install sequence as the CI job): npm run build,
type-check, and lint on src-app/mfe_packages are clean, and test:unit
passes 627 tests across all workspaces including the four MFEs.
npm ci --dry-run passes in template-mfe; policy:version-check and
policy:template-pin-drift stay green.

Unblocks the composed half of Template Validate on constructorfabric#491.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
GeraBart pushed a commit that referenced this pull request Aug 12, 2026
…int rules

Two develop-side changes broke template-mfe under the composed template
validation that PR #491 wires up (nothing on develop runs it, so both
drifted silently):

- 3ea1ee9 moved template-shell to @types/react 19.2.18 (useEffectEvent
  needs it) while the four MFE fixture manifests still pinned 19.0.8.
  Composed, the tree installs both copies and _blank-mfe's type-check
  dies in button.tsx with TS2786/TS2322 (Radix Slot typed against one
  copy, the component's ref against the other). All four manifests and
  the template-mfe lockfile (mirrors + hoisted entry, registry
  integrity) move to 19.2.18.

- The composed eslint run resolves eslint-plugin-react-hooks 7.1.1
  upward from the repo root, and its recommended set flags the MFE
  screens' bridge-resync pattern (set-state-in-effect) — the same
  violations #491 fixed in the shell's own hooks and deferred for the
  five MFE screens. Fixed with the same patterns the shell uses:

  - HomeScreen (_blank), HelloWorldScreen, CurrentThemeScreen,
    ProfileScreen, UIKitElementsScreen: initial theme/language read in
    lazy useState initializers (first paint now reflects the host's
    shared properties) with the effect reduced to subscriptions.
  - ProfileDetailsCard, date-picker: 'adjusting state during render'
    (react.dev) with a prev-key comparison instead of a sync-with-props
    effect.
  - data-table: targeted eslint-disable for
    react-hooks/incompatible-library — TanStack Table's useReactTable
    is documented as uncompilable, and the composed lint runs with
    --max-warnings 0.

CodeRabbit's review then flagged that the four bridge-synced screens
never apply the text direction for the initial language — only the
subscription callbacks set dir, so an initially-RTL host renders LTR
until the next language event. That gap predates this PR, but with
language now correct from the first render the fix is natural: each
screen gets one effect keyed on the language state that applies the
shadow-host dir after commit, covering the initial value and every
later change. That effect subsumes the per-callback dir duplication
(callbacks shrink to setLanguage) and collapses UIKitElementsScreen's
separate initial-dir bridge read into the same shared shape.

Verified on a locally composed shell+overlay tree (the same copy,
lockfile-drop, npm install sequence as the CI job): npm run build,
type-check, and lint on src-app/mfe_packages are clean, and test:unit
passes 627 tests across all workspaces including the four MFEs.
npm ci --dry-run passes in template-mfe; policy:version-check and
policy:template-pin-drift stay green.

Unblocks the composed half of Template Validate on #491.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Aug 13, 2026
…ts/ type-checking (constructorfabric#483)

Adds two CI gates that previously ran only by hand:

- `template-validate` job: validates template-shell standalone and
  template-mfe composed onto template-shell (build, type-check,
  arch:deps, lint, test:unit for both), classifying templates by what
  their manifest CLAIMS rather than disk presence.
- `type-check:scripts` (tsconfig.scripts.json), wired into
  `type-check:all` and CI's TypeScript validation step, so `scripts/`
  gets the same type coverage as the rest of the monorepo.

Includes fixes from @itechmeat's review of constructorfabric#491:
- Structural FileSystemLike typing for link-template-ecosystem.mjs's
  injected fs, needed once type-check:scripts started covering it —
  re-ported onto constructorfabric#518's rewrite of the script during rebase. The gate
  paid for itself immediately: it caught the rewrite's rollback message
  printing a literal "undefined" recovery line when every package was
  restored (recoveryLine assigned in two of three branches), fixed here.
- JSDoc annotations for constructorfabric#493's new scripts (validate-templates,
  template-discovery, template-ecosystem-packages, template-pin-drift)
  and their tests, which predate the type-check:scripts gate.
- template-shell's ecosystem pins moved to 0.3.0-alpha.1 (the
  FRONTX_ACTION_*/DomainContext.typeSystem move constructorfabric#485 recorded), and a
  lockfile self-link entry corrupted independently in develop, fixed.
  Also synced the lockfile to develop's api alpha.1 pin bump (309d77f
  updated package.json only — nothing on develop runs `npm ci` inside
  the template, so the desync was green there and red on this job's
  first standalone install).
- Classify/compose steps refuse a non-empty ownershipBoundaries.sharedFiles
  instead of half-implementing the merge-strategy contract; the overlay
  MFE-package count is per-overlay (from the manifest's own subtree paths)
  instead of one aggregate that could mask a broken overlay behind a
  working one; the composed lockfile cleanup reads the same subtree paths
  instead of hardcoding mfe_packages.
- Workflow-level `permissions: contents: read` and
  `persist-credentials: false` on every checkout, not just
  template-validate's.
- template-validate drops `npm run build:packages`: with the pins on
  registry tarballs, nothing in the job reads the workspace packages'
  dist/ output.
- useCanAccess.ts/useScreenTranslations.ts @cpt- marker regions no
  longer duplicate or drop the behavior they're supposed to trace;
  inst-pending-effect marks the one render-time re-pessimize site.
- Shared DirEntryLike typedef (scripts/fs-types.mjs) instead of two
  independently-drifting copies.
- Comment sweep: change-history framing ("used to", "previously",
  constructorfabric#485's alpha.0-to-alpha.1 story told twice) rewritten as present-tense
  descriptions of the code that is there.

- template-shell's .dependency-cruiser.cjs matches node_modules at any
  depth in doNotFollow, not just the root: the composed tree nests a
  node_modules under each overlaid src-app/mfe_packages/* workspace, and
  the anchored pattern let dependency-cruiser traverse the entire
  installed dependency universe — OOM at the default heap. Standalone
  370 modules, composed 532, both green.

Version bumps (alpha) for the packages this change touches:
frontx-template-shell 0.1.0-alpha.2 (develop took alpha.1 for the constructorfabric#476
pin fix); framework, react, blank-mfe, demo-mfe 0.2.0-alpha.1.

Deferred to follow-ups, tracked in constructorfabric#502, constructorfabric#515, constructorfabric#516: the RTL/bridge-resync
duplication across five MFE screens, a shared useLatest helper for three
deps-less ref-write effects (blocked on eslint-plugin-react-hooks not
recognizing custom-hook-returned refs), and documenting useApiStream's
status lifecycle against architecture/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 33daf83 to 9c47ef3 Compare August 13, 2026 04:05
…ts/ type-checking (constructorfabric#483)

Adds two CI gates that previously ran only by hand:

- `template-validate` job: validates template-shell standalone and
  template-mfe composed onto template-shell (build, type-check,
  arch:deps, lint, test:unit for both), classifying templates by what
  their manifest CLAIMS rather than disk presence.
- `type-check:scripts` (tsconfig.scripts.json), wired into
  `type-check:all` and CI's TypeScript validation step, so `scripts/`
  gets the same type coverage as the rest of the monorepo.

Includes fixes from @itechmeat's review of constructorfabric#491:
- Structural FileSystemLike typing for link-template-ecosystem.mjs's
  injected fs, needed once type-check:scripts started covering it —
  re-ported onto constructorfabric#518's rewrite of the script during rebase. The gate
  paid for itself immediately: it caught the rewrite's rollback message
  printing a literal "undefined" recovery line when every package was
  restored (recoveryLine assigned in two of three branches), fixed here.
- JSDoc annotations for constructorfabric#493's new scripts (validate-templates,
  template-discovery, template-ecosystem-packages, template-pin-drift)
  and their tests, which predate the type-check:scripts gate.
- template-shell's ecosystem pins moved to 0.3.0-alpha.1 (the
  FRONTX_ACTION_*/DomainContext.typeSystem move constructorfabric#485 recorded), and a
  lockfile self-link entry corrupted independently in develop, fixed.
  Also synced the lockfile to develop's api alpha.1 pin bump (309d77f
  updated package.json only — nothing on develop runs `npm ci` inside
  the template, so the desync was green there and red on this job's
  first standalone install).
- Classify/compose steps refuse a non-empty ownershipBoundaries.sharedFiles
  instead of half-implementing the merge-strategy contract; the overlay
  MFE-package count is per-overlay (from the manifest's own subtree paths)
  instead of one aggregate that could mask a broken overlay behind a
  working one; the composed lockfile cleanup reads the same subtree paths
  instead of hardcoding mfe_packages.
- Workflow-level `permissions: contents: read` and
  `persist-credentials: false` on every checkout, not just
  template-validate's.
- template-validate drops `npm run build:packages`: with the pins on
  registry tarballs, nothing in the job reads the workspace packages'
  dist/ output.
- useCanAccess.ts/useScreenTranslations.ts @cpt- marker regions no
  longer duplicate or drop the behavior they're supposed to trace;
  inst-pending-effect marks the one render-time re-pessimize site.
- Shared DirEntryLike typedef (scripts/fs-types.mjs) instead of two
  independently-drifting copies.
- Comment sweep: change-history framing ("used to", "previously",
  constructorfabric#485's alpha.0-to-alpha.1 story told twice) rewritten as present-tense
  descriptions of the code that is there.

- template-shell's .dependency-cruiser.cjs matches node_modules at any
  depth in doNotFollow, not just the root: the composed tree nests a
  node_modules under each overlaid src-app/mfe_packages/* workspace, and
  the anchored pattern let dependency-cruiser traverse the entire
  installed dependency universe — OOM at the default heap. Standalone
  370 modules, composed 532, both green.

Version bumps (alpha) for the packages this change touches:
frontx-template-shell 0.1.0-alpha.2 (develop took alpha.1 for the constructorfabric#476
pin fix); framework, react, blank-mfe, demo-mfe 0.2.0-alpha.1.

Deferred to follow-ups, tracked in constructorfabric#502, constructorfabric#515, constructorfabric#516: the RTL/bridge-resync
duplication across five MFE screens, a shared useLatest helper for three
deps-less ref-write effects (blocked on eslint-plugin-react-hooks not
recognizing custom-hook-returned refs), and documenting useApiStream's
status lifecycle against architecture/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
@tscbmstubp
tscbmstubp force-pushed the feature/483-run-orphaned-checks branch from 9c47ef3 to 6c053fa Compare August 13, 2026 04:11
@GeraBart
GeraBart merged commit f2cf456 into constructorfabric:develop Aug 13, 2026
10 checks passed
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Sep 3, 2026
…ed hooks (constructorfabric#502)

Extract the RTL_LANGUAGES const, the readBridgeProperty helper, the
prevBridge render-time re-read block, and the host dir effect — pasted
verbatim into four demo-mfe screens by constructorfabric#491 — into two shared hooks:

- useBridgeProperty(bridge, propertyId, fallback): lazy initial read,
  bridge-swap resync during render, and change subscription. The module
  doc explains why it is not useSyncExternalStore (non-string updates
  keep the last string value), how it differs from useSharedProperty in
  @gears-frontx/react, and that propertyId must stay constant.
- useHostDirection(containerRef, language): Shadow DOM host dir sync,
  with a readonly RTL_LANGUAGES and the reason for the forced
  HTMLElement cast.

The bridge-swap behaviour is now pinned once by useBridgeProperty's own
tests instead of per-screen; the tests are split per behaviour and cover
the truly-unset and non-string-value inputs, and useHostDirection's tests
use a real shadow root with afterEach host cleanup. The _blank-mfe copy
stays inline per the issue: no-cross-mfe-imports forbids importing from
demo-mfe, and the per-MFE src/shared/ duplication is the existing
convention.

Residue @cpt- markers are stripped from the modified template screens
(ADR-0033: template-territory markers are non-authoritative residue
removed when a file is otherwise modified).

Closes constructorfabric#502

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
tscbmstubp added a commit to tscbmstubp/gears-frontx that referenced this pull request Sep 8, 2026
…ared hooks (constructorfabric#502)

Extract the RTL_LANGUAGES const, the readBridgeProperty helper, the
property subscription, and the host dir effect — pasted verbatim into
four demo-mfe screens by constructorfabric#491 — into two shared hooks:

- useBridgeProperty<T>(bridge, propertyId, fallback): lazy initial read
  and change subscription with cleanup. The value is passed through as
  the caller's T; schema validation belongs to the type-system plugin,
  so the hook does no runtime type filtering. The module doc explains
  how it differs from useSharedProperty in @gears-frontx/react.
- useHostDirection(containerRef, language): Shadow DOM host dir sync,
  with a readonly RTL_LANGUAGES and the reason for the forced
  HTMLElement cast.

The prevBridge render-time resync the screens carried is dropped rather
than extracted: the runtime retains one bridge per extension across
every mount/unmount cycle (MfeBridge contract in @gears-frontx/mfes
handler types) and ThemeAwareReactLifecycle renders a fresh root per
mount, so a mounted screen never sees a different bridge instance. The
four screen tests pinning that swap are removed with it.

useBridgeProperty's tests cover initial read, fallback when the
property is not yet published, non-string pass-through, update
propagation, and unsubscribe on unmount; useHostDirection's tests use a
real shadow root with afterEach host cleanup. The _blank-mfe copy stays
inline per the issue: no-cross-mfe-imports forbids importing from
demo-mfe, and the per-MFE src/shared/ duplication is the existing
convention.

Residue @cpt- markers are stripped from the modified template screens
(ADR-0033: template-territory markers are non-authoritative residue
removed when a file is otherwise modified).

Closes constructorfabric#502

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
GeraBart pushed a commit that referenced this pull request Sep 8, 2026
…ared hooks (#502)

Extract the RTL_LANGUAGES const, the readBridgeProperty helper, the
property subscription, and the host dir effect — pasted verbatim into
four demo-mfe screens by #491 — into two shared hooks:

- useBridgeProperty<T>(bridge, propertyId, fallback): lazy initial read
  and change subscription with cleanup. The value is passed through as
  the caller's T; schema validation belongs to the type-system plugin,
  so the hook does no runtime type filtering. The module doc explains
  how it differs from useSharedProperty in @gears-frontx/react.
- useHostDirection(containerRef, language): Shadow DOM host dir sync,
  with a readonly RTL_LANGUAGES and the reason for the forced
  HTMLElement cast.

The prevBridge render-time resync the screens carried is dropped rather
than extracted: the runtime retains one bridge per extension across
every mount/unmount cycle (MfeBridge contract in @gears-frontx/mfes
handler types) and ThemeAwareReactLifecycle renders a fresh root per
mount, so a mounted screen never sees a different bridge instance. The
four screen tests pinning that swap are removed with it.

useBridgeProperty's tests cover initial read, fallback when the
property is not yet published, non-string pass-through, update
propagation, and unsubscribe on unmount; useHostDirection's tests use a
real shadow root with afterEach host cleanup. The _blank-mfe copy stays
inline per the issue: no-cross-mfe-imports forbids importing from
demo-mfe, and the per-MFE src/shared/ duplication is the existing
convention.

Residue @cpt- markers are stripped from the modified template screens
(ADR-0033: template-territory markers are non-authoritative residue
removed when a file is otherwise modified).

Closes #502

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Vuk D. <davydowiktor@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants