• Projects
  • Service
  • About
  • branding.bz
  • Podcast
  • Tips
  • FAQ
  • Recruit
  • Download
  • Contact
  • branding.bz(ブランド構築SaaS)
  • DESIGN NOW(デザインメディア)
  • X
  • LinkedIn
  • Spotify
  • Facebook

213-0011 神奈川県川崎市高津区久本3-6-7-303

© 2026 ID INC. All rights reserved

claude-skills/スキル
SKILLOfficialdevelopment

modernize-flp-sandbox

プラグイン
ui5-modernization
ソース
GitHub で見る ↗
説明

次のような場合に使用: 従来のFLP サンドボックス(本番環境に近い試験環境)から新しいサンドボックスへとUI5アプリケーションを移行する場合。/modernize-flp-sandbox、「flpSandbox.html」や「sap-ushell-config」への言及、またはサンドボックス設定の更新リクエストで起動します。

原文を表示

Use when migrating UI5 apps from legacy FLP sandbox to the new sandbox (New Sandbox). Triggers on /modernize-flp-sandbox, mentions of "flpSandbox.html", "sap-ushell-config", or requests to update sandbox configuration.

ユースケース
  • UI5アプリケーションを新しいサンドボックスへ移行する
  • サンドボックス設定を更新する
本文

New Sandbox Migration Skill

Migrate a UI5 application from the legacy FLP sandbox to New Sandbox. You analyze, transform, verify, and report. The skill is fully automatic for the core migration; for adjacent concerns (see scope below) it asks the consumer before acting.

Read references/operations.md now — it is the operational reference for all HTML / JSON / hook-module transformations.

Read references/sandbox-config-surface.md now — it is the ground-truth description of what New Sandbox allows, blocks, and silently overrides. All §6 rules cite this file rather than restating constraints inline.

Scope — three layers

  1. Core migration — actions necessary for the app to boot under New Sandbox. Performed unconditionally; fails migration if impossible. Triggers: §6a, §6b, §6c, §6f.

  2. Test infrastructure — gets the test suite running again without changing test semantics. Safe rewrites applied unconditionally (resource-root rebind, OPA bootstrap extraction). Anything touching test logic: detect, report, offer on request. Triggers: §6d, §6e, §6g, §6h, §6j, §6l.

  3. Adjacent migrations & advisories — concerns surfaced by the migration but not part of it. Detect and report only; no rewrites applied.

    • QUnit 1.x → 2.x patterns (§6i) — advisory.
    • Shell-feature tests (§6j, §6l) — advisory.
    • Deprecated ushell services (§6k) — detected in core pass, reported as "Manual action required" (hard runtime block).

1. Detect App Root

If the user provided a path argument, use it. Otherwise, detect from CWD:

  • Look for package.json + webapp/ in CWD and parent directories
  • If not found, tell the user: "Could not detect a UI5 app root. Please run from inside the app directory or provide a path: /modernize-flp-sandbox ~/path/to/app"

Set APP_ROOT to the resolved absolute path.

2. Ensure Clean State (Pre-Migration)

Before touching any files, secure a rollback point.

If git repository detected:

cd $APP_ROOT
git stash push -m "modernize-flp-sandbox: pre-migration backup $(date +%Y%m%d-%H%M%S)"

Save the stash ref for rollback. If nothing to stash, the tree is already clean.

If no git repository:

mkdir -p $APP_ROOT/webapp/test/.migration-backup
cp $APP_ROOT/webapp/test/flpSandbox*.html $APP_ROOT/webapp/test/.migration-backup/ 2>/dev/null
cp $APP_ROOT/webapp/test/fioriSandboxAppConfig.json $APP_ROOT/webapp/test/.migration-backup/ 2>/dev/null

3. Analyze

Read all HTML files under $APP_ROOT/webapp/test/ (recursive) and build a pattern inventory.

Detect legacy sandbox HTML files — a file is legacy if it contains ANY of:

  • id="sap-ushell-bootstrap" (sandbox bootstrap script tag)
  • window["sap-ushell-config"] assignment
  • src= referencing sandbox2.js (intermediate New Sandbox old-style bootstrap — predates SandboxBootTask.js; treat identically to other legacy patterns)

OPA test-page (does NOT receive SandboxBootTask / boot-manifest): A file matches legacy detection AND ALSO contains ALL of:

  • QUnit.config or QUnit.config.autostart assignment, OR window.QUnit = {
  • sap.ui.require( with entries from sap/ui/qunit/, sap/ui/test/, or sap/ui/thirdparty/qunit

These files are NOT migrated as sandbox HTMLs. They receive: (a) §6g bootstrap extraction into sibling JS, (b) §6i QUnit 1.x detection → sub-skill handoff on consent. The §6g HTML edits:

  • Remove <script src="../ushellConfig.js"> and <script src="...sandbox.js" id="sap-ushell-bootstrap">
  • Replace inline QUnit/OPA bootstrap with direct script-tag loading (qunit-2.css, qunit-2.js, qunit-junit.js) + <script src="AllJourneys.js">
  • Create AllJourneys.js from inline content (see §6g)
  • Update data-sap-ui-preload="async" → data-sap-ui-async="true", rename data-sap-ui-compatVersion → data-sap-ui-compat-version, data-sap-ui-resourceroots → data-sap-ui-resource-roots
  • Do NOT add SandboxBootTask.js, boot-manifest, or <div id="canvas">

Externalized ushell config detection: For each <script src="..."> in any HTML under webapp/test/, check if the referenced file contains an assignment to the ushell-config object via:

  • window["sap-ushell-config"] = … / globalThis[…] / self[…]
  • Object.assign(<global>["sap-ushell-config"], …)
  • <global>["sap-ushell-config"].<prop> = … (property-write after initializer)

Files that only read the config do NOT qualify. Record each qualifying file as externalUshellConfigFile. For migration: parse the config identically to inline, remove the <script> include from all referencing HTMLs, delete the file in Step 9.

For each legacy HTML file, record:

  • Filename, has mock server?, has RTA/LREP?, has custom plugins?, has deprecated services?
  • Has locate-reuse-libs.js? (flag for Gap-Report)
  • Existing data-sap-ui-libs, data-sap-ui-resourceroots/data-sap-ui-resource-roots, data-sap-ui-theme, data-sap-ui-language values (carry over, rename to kebab-case)

Check for existing New Sandbox artifacts:

  • fioriSandboxAppConfig.json — exists? (will be created/overwritten)
  • sandbox/ directory — for each *.js file, classify:
    • legacy if contains Container.createRendererInternal OR attachRendererCreatedEvent OR does NOT contain execute:. Capture for in-place rewrite (§6c). Capture top-level namespace declarations as preservedDeclarations[] (regex: ^\s*sap(\.[a-zA-Z0-9_]+)+\s*\?\?=\s*\{\} and globalThis.sap/window.sap chains; fallback: copy verbatim until first sap.ui.define( or IIFE).
    • modern if exports { execute: ... }. Reuse untouched.
    • Multiple legacy files: rewrite ALL. Only one wired via beforeFlpStart — prefer name containing Init (not Mock). Emit Gap-Report note.
  • FakeLREP file (*Lrep*.json / *LRep*.json under webapp/test/) — note exact filename for rta reference.

Check for OPA test wiring:

  • OPA test runner HTML (default webapp/test/integration/opaTests.qunit.html; fallback: any *qunit.html under webapp/test/integration/ referencing the legacy mockserver HTML) — record value matching "../flpSandboxMockServer" → triggers §6d.
  • OPA Common-helper file (default webapp/test/integration/pages/Common.js; fallback: any *.js under webapp/test/integration/ containing iStartMyAppInAFrame(/getFrameUrl( AND sap.ui.require.toUrl() — triggers §6e.

Scan for deprecated ushell service usage: Search *.js under webapp/ (excluding test/, resources/, *.min.js) for getService(<name>) / getServiceAsync(<name>) where <name> is one of the 12 deprecated services in references/sandbox-config-surface.md §5. Record file, line, service name, bound variable. Surface in Gap-Report (§8); follow-up in §6k.

Check UI5 framework version: Read ui5.yaml and ui5-local.yaml for framework.version. New Sandbox requires >= 1.147. If below, auto-bump:

  1. Find latest stable SAPUI5 version >= 1.147
  2. Write to ui5.yaml in-place
  3. Log: "Auto-bumped ui5.yaml framework version from <old> to <new> (New Sandbox requires >= 1.147)."
  4. Note in Gap-Report.

3a. Hook Dependency Graph Scan

Identifies eager sap/ushell/* imports in the transitive AMD graph reachable from the beforeFlpStart hook (Hard Constraint H2 — see references/sandbox-config-surface.md §1). Detail and rewrite recipe in references/operations.md §6f.

This step builds inventory only. Action happens in §6f (after hook is generated in §6c).

Record:

  1. hookEntryModule — resolve from existing fioriSandboxAppConfig.json beforeFlpStart, or detect from legacy hook in §3 (typically webapp/test/sandbox/fioriSandboxInit.js).
  2. hookGraphRoots[] — additional modules the hook requires directly (from inspecting legacy hook body).

4. Scenario Wizard (only when multiple flp*.html found)

Skip if only one legacy sandbox HTML found.

New Sandbox uses a single fioriSandboxAppConfig.json — multiple HTML files cannot have independent configurations. Solution: consolidate into one HTML with a URL parameter selecting the scenario at runtime.

Non-interactive mode: Check for $APP_ROOT/webapp/test/wizard-answers.json. If exists, use its values directly (CI/scripted migrations). Format:

{
    "scenarios": [
        { "file": "flpSandbox.html", "id": "default", "description": "Live backend" },
        { "file": "flpSandboxMockServer.html", "id": "mockserver", "description": "Mock server" }
    ],
    "defaultScenario": "mockserver",
    "targetHtml": "flpSandbox.html",
    "paramName": "scenario"
}

Ask the user:

  1. "What scenario does each file represent?" (e.g., "mockserver", "cdm", "default/no-mock")
  2. "Which scenario should be default?" (Recommend: mockserver — works offline)
  3. "Which HTML filename should be kept?"
  4. "URL parameter name?" (Default: scenario; project-specific name avoids collisions)

Record: target HTML, scenario list, default scenario ID, parameter name, obsolete HTML files.

URL convention: flpSandbox.html?scenario=mockserver. No param → default scenario. Document chosen name in README.

5. Pre-Migration Checklist

Before writing files, verify: APP_ROOT set (§1), rollback secured (§2), inventory built (§3), wizard answers available if needed (§4). All good → proceed to §6.

6. Migrate

Execute all transformations. If any write fails, jump to ROLLBACK (§10).

Scope — files modified:

  • All flp*.html detected in §3 → full transformation (§6a–§6c)
  • OPA test-page HTMLs → bootstrap extraction (§6g)
  • OPA test runner HTML → resource-root rebind (§6d)
  • QUnit test suite index → journey-URL rewrite (§6g)
  • OPA Common-helper → URL-param injection (§6e)
  • webapp/test/fioriSandboxAppConfig.json → create/overwrite (§6b)
  • webapp/test/sandbox/*.js legacy hooks → rewrite in-place (§6c)
  • Files in beforeFlpStart AMD graph → auto-apply references/native-replacements.md (§6f)
  • OPA test code under webapp/test/integration/ and app code → §6h–§6l mechanical rewrites

Out of scope: unitTests.qunit.html, unit/, *.qunit.js.

When flpSandboxMockServer.html is referenced by opaTests.qunit.html, migrate it (§6a) AND rebind the OPA reference (§6d) together.

Each subsection below states what/when/which-layer. Full algorithms live in references/operations.md.

6a. Transform legacy HTML file(s) in-place

Layer: core. Unconditional on every legacy sandbox HTML.

Removes legacy ushell-config write, sap-ushell-bootstrap script tag, obsolete bootstrap attributes. Adds SandboxBootTask.js (or CDN variant), boot-manifest attributes, <div id="canvas">. Merges resource roots across variants, always adds sandbox root.

→ references/operations.md §6a

6b. Create or update fioriSandboxAppConfig.json

Layer: core. Honors only keys in references/sandbox-config-surface.md §2.

Builds JSON from parsed legacy config. Splits application keys on first - into semanticObject + action. Strips query strings from rootPath, ensures trailing slash. Aggregates tiles across variants when Wizard ran. Adds beforeFlpStart, rta, plugins only when warranted.

→ references/operations.md §6b

6c. Create or rewrite hook module

Layer: core. Backs beforeFlpStart, runs before applyUshellConfig. Contract: no globalThis["sap-ushell-config"] touch, no eager sap/ushell/* require (see references/sandbox-config-surface.md §8).

Produces single-scenario hook (mock-server only) or multi-scenario hook (URL-parameter switch). Rewrites legacy hooks in place preserving namespace declarations. Falls back to minimal no-op when no mock server needed.

→ references/operations.md §6c

6d. Rebind OPA resource roots

Layer: test-infra. Unconditional (no semantics change).

In OPA test runner HTML, rewrites data-sap-ui-resource-roots pointing at legacy mockserver HTML to point at migrated target.

→ references/operations.md §6d

6e. Inject scenario URL parameter into Common.js

Layer: test-infra. Only when Wizard consolidated multiple HTMLs.

Injects scenario parameter into iframe URL before the # hash (so window.location.search sees it).

→ references/operations.md §6e

6f. Resolve hook-graph ushell dependencies

Layer: core. Hard runtime block H2 — no sap/ushell/* may be eagerly required from hook's transitive AMD graph.

Walks AMD closure from hookEntryModule (§3a). Classifies each sap/ushell/* hit as trivial-replaceable / architectural-relocatable / manual-required. Auto-applies recipes from references/native-replacements.md or emits Gap-Report entry.

→ references/operations.md §6f

6g. Extract OPA bootstrap into a sibling JS file

Layer: test-infra. Mechanical extraction.

Extracts inline <script> block into sibling .js (default AllJourneys.js). Converts QUnit 1.x globals and jQuery.sap.getUriParameters to modern equivalents. Updates test-suite index to URLSearchParams-style journey URLs.

→ references/operations.md §6g

6h. Detect bindings to legacy ushell-config values

Layer: test-infra (auto-fix where mechanical, report otherwise).

Identifies code hard-coding values that were free-form in legacy config but are now derived differently under New Sandbox. Categories: A tile-derived (auto-fix), B user-profile (auto-fix), C personalization (auto-fix), D fixed-by-default (report only). See references/sandbox-config-surface.md §3+§4.

→ references/operations.md §6h

6i. QUnit 1.x → 2.x patterns (handoff)

Layer: advisory. Actual rewrite in modernize-flp-sandbox-qunit sub-skill.

Detects, reports, offers to invoke sub-skill. Why surfaced: §6a adds data-sap-ui-async="true" — QUnit 1.x globals (module, ok, equal) throw ReferenceError in that mode. Root cause is independent of sandbox migration; the migration just exposes it.

→ references/operations.md §6i

6j. FLP shell-control awareness (reporting)

Layer: test-infra (report only). Detects OPA tests targeting FLP shell controls directly. Shell renders through Web Components in newer UI5 — tests matching sap.m.* shell controls break silently.

Patterns: S1 = sap.m control + shell-only id, S2 = type:"Back" matcher, S3 = non-WebComponent shell header calls.

→ references/operations.md §6j

6k. Deprecated ushell-services in app code (detection)

Layer: core detection. Every deprecated service is a hard runtime block at getService()/getServiceAsync() time (see references/sandbox-config-surface.md §5). App won't boot.

Scans app code, records hits, surfaces in Gap-Report as "Manual action required". No rewrite attempted.

→ references/operations.md §6k

6l. OPA tests exercising FLP-shell features (detection + ask)

Layer: test-infra (detection + ask). Detects journey tests dependent on FLP shell. Only offers to apply fix if recognised iframe-toggle pattern exists. Never modifies without consent.

Signals: shell-control selectors (§6j), deprecated service calls (§6k), convention-named page-object methods. Probes: P1 = startMyAppInAFrame flag, P2 = iStartMyAppInAFrame helper, P3 = bespoke iframe URL builder.

→ references/operations.md §6l

8. Report

Always emit the Gap-Report:

== New Sandbox Migration Report ==

App:    <app name from package.json>
Path:   <APP_ROOT>
Status: ✓ SUCCESSFUL  |  ✗ FAILED

── Automatically applied ──────────────────────────────────────────────
  ✓/✗  webapp/test/<filename>.html              (HTML transformed)
  ✓/✗  webapp/test/fioriSandboxAppConfig.json   (created)
  ✓/—  webapp/test/sandbox/<hookModule>.js      (created / reused / rewrote-legacy)
  ✓/—  rta: "<fakeLRep filename>"               (written to config)
  ✓/—  opaTests.qunit.html                      (resource root rebound)
  ✓/—  Common.js                                (scenario URL param injected)
  ✓/—  Hook-graph: <N> trivial replacement(s) auto-applied

── Manual action required ─────────────────────────────────────────────
  ✗  <ServiceName> (deprecated — hard runtime error): <file>:<line>
     → <successor from sandbox-config-surface.md §5>

  ✗  Custom FakeLrep connector at <path>
     → May have sap/ushell dependencies incompatible with beforeFlpStart.

  ✗  Hook-graph — architectural-relocatable: <module> uses <sap/ushell/X>
     → [diff sketch]

  ✗  Hook-graph — manual-required: <module> uses <sap/ushell/X> at load time
     → [textual sketch]

  ✗  <Layer-2 step> — pattern not recognised
     → [description]

── Advisory (no migration blocker) ───────────────────────────────────
  ℹ  <N> QUnit 1.x pattern(s) in <M> file(s)
  ℹ  Shell-control test patterns: <N> in <M> files (S1: ?, S2: ?, S3: ?)
  ℹ  locate-reuse-libs.js: script tag removed — deprecated pattern, safe.
  ℹ  <other non-standard patterns>

[On failure: "Rolled back. Partial attempt saved to webapp/test/.migration-attempt/"]

Sections with no findings are omitted from the report.

9. Legacy File Cleanup (REQUIRED — do not skip)

  • No Wizard: legacy HTMLs transformed in-place — no extra files to delete.
  • Wizard used: delete all obsolete HTML files (everything except target).
  • Always: delete each externalUshellConfigFile[].
rm <obsolete-file-1> <obsolete-file-2> ...

Verify: ls webapp/test/flp*.html — only the migrated target remains.

10. Rollback

On any failure during §6:

Save partial attempt:

mkdir -p $APP_ROOT/webapp/test/.migration-attempt
cp $APP_ROOT/webapp/test/*.html $APP_ROOT/webapp/test/.migration-attempt/ 2>/dev/null
cp $APP_ROOT/webapp/test/fioriSandboxAppConfig.json $APP_ROOT/webapp/test/.migration-attempt/ 2>/dev/null

Restore:

  • Git: git checkout -- webapp/test/ && git stash pop
  • No git: cp $APP_ROOT/webapp/test/.migration-backup/* $APP_ROOT/webapp/test/

Emit Gap-Report with status FAILED.

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。