Skip to content

feat(install): wire react-native preset into install.sh (closes multi-stack umbrella #646) - #714

Merged
artyhoo merged 2 commits into
stagingfrom
claude/react-native-install-wiring
Jun 24, 2026
Merged

feat(install): wire react-native preset into install.sh (closes multi-stack umbrella #646)#714
artyhoo merged 2 commits into
stagingfrom
claude/react-native-install-wiring

Conversation

@artyhoo

@artyhoo artyhoo commented Jun 24, 2026

Copy link
Copy Markdown
Owner

What

Second half of the multi-stack-install-wiring-iphase umbrella (issue #646 Stage 1). react-spa was wired in #713; this wires react-native, making install.sh react-native a fully installable stack and closing the umbrella (both presets now installable). ts-server/react-next/react-spa paths stay byte-identical (verified --dry-run: 0 react-native leak into the prior stacks).

How (RN diverges — wired per the actual preset, not by blind-mirroring react-next)

  • Two baseline eslint configs (Expo vs bare-RN) — picked by detecting the consumer's deps: "expo" in package.jsoneslint.config.expo.mjs; else eslint.config.bare-rn.mjseslint.config.mjs. The shared eslint.config.rn-common.mjs (which both baselines import) is always copied so the import resolves at ESLint load.
  • No custom eslint-rules (RN ships none) → no preset eslint-rules copy branch, no barrel refs.
  • No playwright (native / web-less; E2E is Detox/Maestro, not wired by install).
  • REACT_NATIVE_DEVDEPS = RN eslint toolchain only (eslint-config-expo, @react-native/eslint-config + @eslint/eslintrc via FlatCompat, eslint-plugin-react-native(-a11y)).
  • eslint.config.rn-common.mjs registered in ignore_shipped_configs candidates[] — the gh-531 prettier-ignore drift guard caught the new basename escaping the conditional ignore (rules-as-tests working as intended); fixed in the same change.
  • Stack selection: arg parser, guard, interactive menu (4) react-native), --refresh auto-detect.

Self-application gates extended:

  • principle 09 (SHIPPED_DOCS ↔ REQUIRED_HEADER_DOCS): +3 react-native docs (count 2225, shape sentinel 6972, SHIPPED_DOC_PREFIXES += packages/preset-react-native/).
  • principle 05: react-native RULES.md is static (non-manifest-rendered) → out of manifest-drift scope (scope comment generalized to both new presets).
  • New paired-negative test tests/install-sh/react-native-wiring.test.sh (RED→GREEN) + wired into audit-self.yml (meta-all-wired green).

Verification (evidence, per T3)

principle suite ........ 27 files, 229 tests passed
tsc --noEmit (core) .... clean
install-sh suite ....... PASS=45 FAIL=0  (incl. new react-native-wiring + gh-531 fix)
react-native-wiring .... RED 2/9 (pre-fix, "Unknown stack") → GREEN 9/9 (post-fix)
dry-run all 4 stacks ... ts-server/react-next/react-spa byte-identical (0 RN leak);
                         react-native: bare-RN default, Expo-on-expo-dep, rn-common lands, no playwright

Umbrella closure

Writes .claude/orchestrator-prompts/multi-stack-install-wiring-iphase/done.md (both presets wired: react-spa #713 + react-native here).

§1.7 Forward-check applied

Checked against active disciplines. principle 02 (paired-negative): the new test runs a fabricated relative-import through the same resolver and asserts it is flagged unresolved (tests/install-sh/react-native-wiring.test.sh:78), so the import-resolution green is real, not a vacuous empty-loop. principle 09 (doc-authority): the 3 newly-registered RN docs (packages/core/principles/09-doc-authority-hierarchy.ts:98) each already carry an Authoritative-for header (install's author-side verify loop + the principle-09 test both pass). #531 prettier-ignore guard: the new shipped basename was registered in install.sh ignore_shipped_configs candidates[] after gh-531-shipped-prettier.test.sh flagged it — the drift guard did its job. no-paid-llm-in-ci: the new test + workflow step are deterministic bash, zero API calls. capability-commit gate: no new dependency, no new ≥80-LOC file under packages/ (the test is under tests/) → not a capability commit; escape-hatch Prior-art: trailer on the commit.

§1.7 Backward-check applied

Swept the complete set of artefacts under scope ("react-native is an installable stack"). install.sh touchpoint sweep: every react-spa touchpoint (grep -nE 'STACK.*react-spa') has a mirrored react-native branch, adjusted for RN's divergences — arg/guard/menu/refresh-detect/SHIPPED_DOCS/RULES+ARCH/audit-self/templates/dev-deps; the templates branch (install.sh:1102 region) detects Expo-vs-bare and always lands rn-common; no eslint-rules branch and no playwright (RN has neither). --dry-run confirms RN lands its own files and ts-server/react-next/react-spa emit 0 react-native references (byte-identical). shipped-config completeness: gh-531-shipped-prettier.test.sh:66 greps every copy_safe root-config target and asserts it is in candidates[]; eslint.config.rn-common.mjs is now registered and that arm is green. install-sh test-wiring sweep: the new test is wired at .github/workflows/audit-self.yml:307 and meta-all-wired.test.sh is green (non-vacuous). principle 05 exemption (explicit): RN RULES.md static-copy carve-out documented at packages/core/principles/05-manifest-ssot.test.ts:26.

Test plan

  • npm --prefix packages/core run test:principles — 229/229
  • cd packages/core && npx tsc --noEmit — clean
  • tests/install-sh/*.test.sh — 45/45
  • install.sh {ts-server,react-next,react-spa,react-native} --dry-run — all complete; first three byte-identical; RN Expo/bare detect verified

artyhoo added 2 commits June 24, 2026 13:55
…-stack umbrella #646)

Second half of the multi-stack-install-wiring-iphase umbrella (#646 Stage 1):
react-spa was wired in #713; this wires react-native, making `install.sh react-native`
a fully installable stack. ts-server/react-next/react-spa paths stay byte-identical
(verified via --dry-run: 0 react-native leak into the prior stacks).

RN diverges from the web stacks (wired per the ACTUAL preset layout, not by
blind-mirroring react-next — T13/T16):
- TWO baseline eslint configs (Expo vs bare-RN), picked by detecting the consumer's
  deps (`"expo"` in package.json → eslint.config.expo.mjs; else eslint.config.bare-rn.mjs)
  → eslint.config.mjs. The shared eslint.config.rn-common.mjs (BOTH baselines import it)
  is ALWAYS copied so the import resolves at ESLint load.
- NO custom eslint-rules (no preset barrel) → no eslint-rules copy branch.
- NO playwright (native / web-less; E2E is Detox/Maestro, not wired by install).
- REACT_NATIVE_DEVDEPS = RN eslint toolchain only (eslint-config-expo,
  @react-native/eslint-config + @eslint/eslintrc via FlatCompat, eslint-plugin-react-native(-a11y)).
- eslint.config.rn-common.mjs registered in ignore_shipped_configs candidates[] — the
  gh-531 #531 prettier-ignore drift guard caught the new basename escaping the conditional
  ignore (rules-as-tests working as intended); fixed.

Self-application gates extended:
- principle 09 SHIPPED_DOCS↔REQUIRED_HEADER_DOCS: +3 react-native docs (count 22→25,
  shape sentinel 69→72, SHIPPED_DOC_PREFIXES += packages/preset-react-native/).
- principle 05: react-native RULES.md is static (non-manifest-rendered) → out of the
  manifest-drift check's scope (scope comment generalized to both new presets).
- new paired-negative test tests/install-sh/react-native-wiring.test.sh (RED→GREEN:
  Expo+bare-RN detect, rn-common import resolution, non-vacuity arm) wired into audit-self.yml.

Prior-art: skipped — integration wiring (install.sh react-native branches + principle-test
registration) for the react-native preset whose capabilities were already SSOT-cited in the
#646 preset PRs (#142 Expo baseline ADOPT, #143 bare-RN baseline ADOPT); no new dependency,
no new >=80-LOC file under packages/ (the test is under tests/), no new capability.
@artyhoo
artyhoo enabled auto-merge (squash) June 24, 2026 10:59
@artyhoo
artyhoo merged commit 991b811 into staging Jun 24, 2026
28 checks passed
artyhoo added a commit that referenced this pull request Jun 26, 2026
Replace the proprietary "All Rights Reserved" LICENSE.md with the canonical
Functional Source License v1.1 (Copyright 2026 Art) — each version auto-converts
to Apache-2.0 on its second anniversary. Set license: "FSL-1.1-ALv2" across the
root workspace package.json and all 7 workspace packages (core, lint-config,
meta-factory, preset-next-15-canonical, preset-react-native, preset-react-spa,
runtime-bridge), mirror the field in package-lock.json, and update the README
license badge + License section.

Scope note: the prepared edits covered 5 packages; preset-react-native (#714)
and preset-react-spa (#713) merged after and were still UNLICENSED — included
here so FSL applies consistently across every workspace package (same concern).

Prior-art: skipped — license application (FSL-1.1-ALv2), no new capability or dependency.
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.

1 participant