[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ACV7ME2VDF1F60XFB5SMPP":3,"skill-same:01M6ACV7ME2VDF1F60XFB5SMPP":828},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":28,"linkOnly":29,"markdownContent":30,"markdownBody":31,"frontMatter":32,"refName":34,"commitSha":35,"skillDirectory":36,"forksCount":37,"repositoryHtmlUrl":38,"repositoryHomepageUrl":39,"ownerHtmlUrl":40,"ownerBlogUrl":41,"ownerDescription":6,"updatedAt":42,"install":43,"resources":55},"01M6ACV7ME2VDF1F60XFB5SMPP","local-boot",null,"Boot the Horizon UI dev env (BFF + UI) against a local OAP or the public Apache demo OAP. Uses the repo's committed, env-driven horizon.yaml — the same config the image ships — and injects the OAP target + dev users purely via HORIZON_* environment variables. Handles the apps\u002Fbff cwd \u002F HORIZON_CONFIG gotcha and the demo OAP password (kept out of git via the cached oap-demo-env-auth.key). Also covers booting with the AI assistant enabled (Amazon Bedrock \u002F DeepSeek), keyed from the git-ignored bedrocks-api.key.","apache\u002Fskywalking-horizon-ui","apache","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F47359?v=4","01M6AC83E6K4FDKK7HZ8WNMQKE","The Apache Software Foundation","01M6ACV2YS1FGZP4TNKNEXCRTY",23,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,9,27],"boot","local boot","image","assistant","auth","config","git","dev","ui","2026-11-10 10:12:30",false,"---\nname: local-boot\ndescription: Boot the Horizon UI dev env (BFF + UI) against a local OAP or the public Apache demo OAP. Uses the repo's committed, env-driven horizon.yaml — the same config the image ships — and injects the OAP target + dev users purely via HORIZON_* environment variables. Handles the apps\u002Fbff cwd \u002F HORIZON_CONFIG gotcha and the demo OAP password (kept out of git via the cached oap-demo-env-auth.key). Also covers booting with the AI assistant enabled (Amazon Bedrock \u002F DeepSeek), keyed from the git-ignored bedrocks-api.key.\nuser-invocable: true\n---\n\n# Boot the Horizon UI local dev env\n\nThere is **one config file**: the repo's committed `horizon.yaml` at the\nrepo root. Every field in it is a `${HORIZON_…:default}` token, so dev boots\nuse the SAME file the Docker image ships and override only what they need via\n**environment variables** — there are no per-scenario config files anymore.\n\nTwo committed helpers live next to this file (throwaway dev values, safe to\ncommit):\n\n- `dev-users.json` — the four local login users (`viewer` \u002F `maintainer` \u002F\n  `operator` \u002F `admin`, **password == username**), as a **single-line** JSON\n  array for `HORIZON_AUTH_LOCAL_USERS`.\n- `dev-ldap.json` — the test-OpenLDAP config for `HORIZON_AUTH_LDAP` (single line).\n\nThe stack: **BFF** (Fastify) on `:8081`, **UI** (Vite) on `:9091` proxying\n`\u002Fapi` → `:8081`. Open **`http:\u002F\u002F127.0.0.1:9091`** (use the IPv4 literal, not\n`localhost` — see the proxy\u002FIPv4 section). Both ports are overridable — see\n\"Custom ports\".\n\n> **JSON env values must be SINGLE-LINE.** `HORIZON_AUTH_LOCAL_USERS`,\n> `HORIZON_OAP_AUTH`, `HORIZON_AUTH_LDAP`, etc. are spliced into the YAML before\n> parsing; a multi-line JSON value breaks the parse (`YAMLParseError: Flow\n> sequence … must be sufficiently indented`). The `dev-*.json` files are already\n> single-line — keep them that way.\n\n## Environment variables (the dev contract)\n\nLocal dev runs as **two processes \u002F two ports**: the BFF (Fastify, owns `\u002Fapi`)\nand Vite (serves the UI, proxies `\u002Fapi` → BFF). The BFF reads `HORIZON_*` via the\nconfig loader's `${VAR:default}` interpolation; Vite reads `BFF_PORT` +\n`UI_DEV_PORT` directly in `apps\u002Fui\u002Fvite.config.ts`.\n\n| Variable                    | Default                    | Used by | Purpose |\n|---|---|---|---|\n| `HORIZON_CONFIG`            | _(none — required)_        | BFF     | **Absolute** path to the config. Always `\"$REPO\u002Fhorizon.yaml\"`. A bare `.\u002Fhorizon.yaml` resolves under `apps\u002Fbff\u002F` — see \"The one gotcha\". |\n| `HORIZON_SERVER_PORT`       | `8081`                     | BFF     | BFF listen port (`server.port`). For a custom port set this AND `BFF_PORT` to the same value. |\n| `BFF_PORT`                  | `8081`                     | UI      | Vite's `\u002Fapi` proxy target. Must match `HORIZON_SERVER_PORT`. |\n| `UI_DEV_PORT`               | `9091`                     | UI      | Vite listen port. Dev-only. |\n| `HORIZON_OAP_QUERY_URL`     | `http:\u002F\u002F127.0.0.1:12800`   | BFF     | OAP GraphQL endpoint. |\n| `HORIZON_OAP_ADMIN_URL`     | `http:\u002F\u002F127.0.0.1:17128`   | BFF     | OAP admin REST endpoint. Often a different port from GraphQL (the demo splits on `:17128`) — if the BFF logs `UITemplate 404`, this is wrong. |\n| `HORIZON_OAP_ZIPKIN_URL`    | `http:\u002F\u002F127.0.0.1:9412\u002Fzipkin` | BFF | Zipkin query endpoint (Zipkin trace layer). |\n| `HORIZON_OAP_TIMEOUT_MS`    | `15000`                    | BFF     | OAP request timeout. Lower it (`4000`) when previewing the \"OAP unreachable\" landing block so errors surface fast. |\n| `HORIZON_OAP_AUTH`          | _(none)_                   | BFF     | OAP basic-auth as JSON, e.g. `{\"username\":\"admin\",\"password\":\"…\"}`. The demo needs it (password from `oap-demo-env-auth.key`). |\n| `HORIZON_AUTH_LOCAL_USERS`  | `[]`                       | BFF     | Local login users (JSON array, single-line). Use `$(cat dev-users.json)`. |\n| `HORIZON_AUTH_TOKENS_FILE`  | _(none)_                   | BFF     | Path to an API-token file — the credential for non-browser callers (scripts, CI, MCP clients). Point it at `\"$SK\u002Fdev-tokens.json\"`, which is **git-ignored and not committed**: mint your own the first time with `pnpm --filter @skywalking-horizon-ui\u002Fbff cli:token admin --label dev`, then paste the printed entry into that file. A working token must never be committed, even a dev one — the repo is public. |\n| `HORIZON_AUTH_BACKEND`      | `local`                    | BFF     | `local` or `ldap`. |\n| `HORIZON_AUTH_LDAP`         | _(none)_                   | BFF     | LDAP config (JSON, single-line) when backend=ldap. Use `$(cat dev-ldap.json)`. |\n| `HORIZON_TEMPLATES_MODE`    | `live`                     | BFF     | `live` (seed + read ui_template) or `readonly` (render the bundle, config read-only). |\n\nRBAC is left to the built-in role defaults (the `horizon.yaml` token\n`roles: ${HORIZON_RBAC_ROLES:null}` falls through to them), so no roles env var\nis needed for dev.\n\n## The one gotcha that bites every time\n\nThe BFF dev script is `tsx watch src\u002Fserver.ts` and pnpm runs it with **cwd =\n`apps\u002Fbff`**. The config path defaults to `.\u002Fhorizon.yaml`, resolved relative to\ncwd — so a bare `.\u002Fhorizon.yaml` points at the non-existent `apps\u002Fbff\u002Fhorizon.yaml`\n(NOT the repo-root one), and the loader silently falls back to schema defaults\nwith **zero users** (every login then fails \"invalid credentials\").\n\n**Always pass `HORIZON_CONFIG` as an ABSOLUTE path:** `\"$REPO\u002Fhorizon.yaml\"`.\n\n## Proxy + IPv4 (the second gotcha)\n\nTwo things make the UI look \"not accessible\" even when Vite is running:\n\n- **Vite binds IPv6 `[::1]` by default**, so `127.0.0.1:9091` (IPv4) has nothing and many browsers \u002F curl fail. **Force IPv4** with `--host 127.0.0.1`. Note `pnpm --filter ui run dev -- --host …` does NOT forward the flag — run the Vite binary directly (`apps\u002Fui\u002Fnode_modules\u002F.bin\u002Fvite --host 127.0.0.1`).\n- **A local proxy** (ClashX \u002F v2ray etc. — `http_proxy` \u002F `https_proxy` \u002F `all_proxy` pointing at `127.0.0.1:\u003Cport>`) intercepts loopback and returns `502`. Detect and bypass it for the dev hosts.\n\nDetect a local proxy before booting:\n```bash\nenv | grep -iE '^(http_proxy|https_proxy|all_proxy)=' && echo \"local proxy detected — will bypass loopback\"\n```\n\nThe browser uses its OWN proxy settings (not the shell's), so the developer must also let `127.0.0.1` \u002F `localhost` go direct (ClashX \"bypass localhost\" \u002F system proxy no-proxy list). The env-level bypass below only fixes CLI tools and Vite's own fetches.\n\n## The stale-process trap (why a config switch \"didn't take\")\n\n`tsx watch` keeps the old BFF alive, so a freshly launched BFF silently dies on `EADDRINUSE: 127.0.0.1:8081` while the OLD process keeps serving the OLD env. Symptom: you switch demo↔local, everything looks fine, but the UI still shows the previous OAP's data.\n\n- `pkill -f \"tsx watch src\u002Fserver.ts\"` may miss the actual listener — also `pkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\"`, and **verify the port is free with `lsof` before relaunching** (loop until free; the watcher respawns a child).\n- After boot, **confirm which OAP the LIVE process uses** — don't trust that your new process won the port:\n  ```bash\n  curl -s --noproxy '*' -b \u002Ftmp\u002Fsw.cookies \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Foap\u002Fconfig\" | grep -oE '\"adminUrl\":\"[^\"]*\"'\n  # local => http:\u002F\u002F127.0.0.1:17128 ; demo => https:\u002F\u002Fdemo.skywalking.apache.org:17128\n  ```\n\n## Boot against the public demo OAP\n\nThe demo OAP needs basic-auth (network username `admin`). The password is NOT\ncommitted — it lives in `oap-demo-env-auth.key` next to this file (git-ignored via\nthe `.claude\u002Fskills\u002Flocal-boot\u002F*.key` rule). Source it; if missing, ask the developer and\nrecreate it (one line, the password only).\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"\nSECRET=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\u002Foap-demo-env-auth.key\"\nif [ -s \"$SECRET\" ]; then\n  OAP_PASSWORD=\"$(cat \"$SECRET\")\"; export OAP_PASSWORD\nelse\n  read -rsp \"Demo OAP password: \" OAP_PASSWORD && export OAP_PASSWORD && echo\n  printf '%s\\n' \"$OAP_PASSWORD\" > \"$SECRET\" && chmod 600 \"$SECRET\"  # cache for next boot\nfi\n\n# Kill prior dev servers + confirm the port is free (see stale-process trap).\npkill -f \"tsx watch src\u002Fserver.ts\" 2>\u002Fdev\u002Fnull\npkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\" 2>\u002Fdev\u002Fnull; pkill -f vite 2>\u002Fdev\u002Fnull\nuntil ! lsof -nP -iTCP:8081 -sTCP:LISTEN >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\n\n# BFF — repo horizon.yaml + everything via env. JSON values are single-line.\nSK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=https:\u002F\u002Fdemo.skywalking.apache.org:12800 \\\nHORIZON_OAP_ADMIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:17128 \\\nHORIZON_OAP_ZIPKIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:9412\u002Fzipkin \\\nHORIZON_OAP_AUTH=\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$OAP_PASSWORD\\\"}\" \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\nHORIZON_AUTH_TOKENS_FILE=\"$SK\u002Fdev-tokens.json\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n\n# UI — IPv4 host + loopback proxy bypass (run the binary directly so --host applies).\n( cd \"$REPO\u002Fapps\u002Fui\" && \\\n  env -u http_proxy -u https_proxy -u all_proxy -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY \\\n      no_proxy=\"localhost,127.0.0.1,::1\" NO_PROXY=\"localhost,127.0.0.1,::1\" \\\n      node_modules\u002F.bin\u002Fvite --host 127.0.0.1 & )\n```\n\nThen open **`http:\u002F\u002F127.0.0.1:9091`** and log in as `admin` \u002F `admin`. To boot in\nread-only template mode, add `HORIZON_TEMPLATES_MODE=readonly` to the BFF line.\n\n## Boot with the AI assistant enabled (Bedrock \u002F DeepSeek)\n\nThe AI assistant (the `ai:` block in `horizon.yaml`) is **off by default** — the\nlauncher stays hidden until the feature is enabled AND a usable provider is\nconfigured. To exercise it in dev, add the `HORIZON_AI_*` env vars below to any\nboot above — usually the **demo** boot, so there is live data to investigate.\n\nThe dev provider is **Amazon Bedrock** running **DeepSeek** (`deepseek.v3.2`,\nregion `us-west-2`). The Bedrock key is a secret kept next to this file:\n\n- `bedrocks-api.key` — a Bedrock **`ABSK…` bearer token**, one line, git-ignored\n  via the `.claude\u002Fskills\u002Flocal-boot\u002F*.key` rule (same rule as the OAP password).\n  If missing, mint one in the AWS console (Bedrock → API keys) and drop it here.\n\nOur config field is **`HORIZON_AI_API_KEY`** — the BFF passes it to the SDK\nexplicitly as `bedrockBearerToken`. Do **NOT** set `AWS_BEARER_TOKEN_BEDROCK`:\nthat is the AWS SDK's own env var, which our code deliberately bypasses so\nconcurrent requests stay isolated. The **only bedrock-specific\nextra is `HORIZON_AI_REGION`** (it falls back to `AWS_REGION` when blank). Our\nbedrock path REQUIRES the bearer key and does **not** use the AWS SSO \u002F IAM\ncredential chain — a missing key is a clean 503, not an SSO prompt.\n\n| Variable                    | Value (dev)               | Purpose |\n|---|---|---|\n| `HORIZON_AI_ENABLED`        | `true`                    | Master switch (default `false`). |\n| `HORIZON_AI_PROVIDER`       | `bedrock`                 | Transport — `openai-compatible` (default) or `bedrock`. |\n| `HORIZON_AI_MODEL`          | `deepseek.v3.2`           | Bedrock model \u002F inference-profile id. |\n| `HORIZON_AI_REGION`         | `us-west-2`               | Bedrock-only extra; falls back to `AWS_REGION`. |\n| `HORIZON_AI_API_KEY`        | `$(cat bedrocks-api.key)` | **Secret** `ABSK` bearer. Redacted from logs. |\n\nAdd these lines to the demo boot's BFF invocation (keep the SECRET \u002F pkill \u002F\nport-free steps from the demo section):\n\n```bash\nSK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=https:\u002F\u002Fdemo.skywalking.apache.org:12800 \\\nHORIZON_OAP_ADMIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:17128 \\\nHORIZON_OAP_ZIPKIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:9412\u002Fzipkin \\\nHORIZON_OAP_AUTH=\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$OAP_PASSWORD\\\"}\" \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\nHORIZON_AI_ENABLED=true \\\nHORIZON_AI_PROVIDER=bedrock \\\nHORIZON_AI_MODEL=deepseek.v3.2 \\\nHORIZON_AI_REGION=us-west-2 \\\nHORIZON_AI_API_KEY=\"$(cat \"$SK\u002Fbedrocks-api.key\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n```\n\nVerify readiness after login — expect `ready:true`:\n```bash\ncurl -s --noproxy '*' -b \u002Ftmp\u002Fsw.cookies \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Fai\u002Fconfig\"\n```\nThen the floating **AI Assistant** launcher appears on the right edge; the chat\nstreams an answer with inline figures (open `\u002Fai` for the full page). **On-demand\npod logs** work when the OAP itself runs in Kubernetes (the public demo does) and\nits `enableOnDemandPodLog` is on — the assistant's `fetch_pod_logs` tool and the\nper-layer Pod Logs tab both read them live.\n\n## Boot with single sign-on (Google and\u002For GitHub)\n\nHorizon can hand the login to identity providers (`auth.sso`). The local dev\nconfig is split three ways, mirroring the split the config schema is heading\ntoward — **a provider says how to authenticate; roles say what you get, and are\nnot per-provider**:\n\n| File | Holds |\n|---|---|\n| `gmail_oauth.config` | Google provider: client id\u002Fsecret + endpoints. Connection only. |\n| `github_oauth.config` | GitHub provider: client id\u002Fsecret + endpoints, `namePath: login`, `emailsEndpoint`. Connection only. |\n| `oauth.config` | ONE role table for every provider: `defaultRoles`, `roleByEmail`, `roleByDomain`. Goes into `auth.sso.roles` verbatim. |\n\nAll three are **git-ignored and must never be committed**: this directory is\ndeny-by-default in `.gitignore`, with only SKILL.md, `dev-users.json`,\n`dev-ldap.json` and `ldap-seed.ldif` allow-listed.\n\n**Why one role table.** Roles resolve from the EMAIL ADDRESS alone — a token\ncarries no provider — so a per-provider role table is a promise the architecture\ncannot keep. Keeping the addresses in one file also avoids the failure that\ncost a debugging session: two providers whose tables disagreed about the same\naddress once resolved to NO roles, and an API token with no roles is refused,\nso adding a second provider logged every agent out with an unexplained 401.\n\n**Use the PACKAGED build, on ONE port.** The dev BFF is API-only, so the\npost-login redirect lands on an SPA route it does not serve and you get a 404\nthat looks like a login failure. `dist\u002Fserver.js` serves the UI and the API\ntogether, exactly as a real deployment does.\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"; SK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\npnpm package                       # if dist\u002F is stale\n\n# Compose the providers with the shared role table. Drop either provider from\n# the list to boot with just one.\nexport HORIZON_AUTH_SSO=$(python3 -c \"\nimport json\nroles = json.load(open('$SK\u002Foauth.config'))\nprov = lambda f: json.load(open(f))['horizon']\nprint(json.dumps({\n  'providers': [prov('$SK\u002Fgmail_oauth.config'), prov('$SK\u002Fgithub_oauth.config')],\n  'roles': {k: roles[k] for k in ('defaultRoles', 'roleByEmail', 'roleByDomain') if k in roles},\n}))\")\n\ncd \"$REPO\u002Fdist\" && NODE_USE_ENV_PROXY=1 \\\n  NO_PROXY=\"demo.skywalking.apache.org,127.0.0.1,localhost,::1\" \\\n  HORIZON_CONFIG=.\u002Fhorizon.yaml \\\n  HORIZON_SERVER_HOST=127.0.0.1 HORIZON_SERVER_PORT=9091 \\\n  HORIZON_PUBLIC_URL=http:\u002F\u002F127.0.0.1:9091 \\\n  HORIZON_OAP_QUERY_URL=https:\u002F\u002Fdemo.skywalking.apache.org:12800 \\\n  HORIZON_OAP_ADMIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:17128 \\\n  HORIZON_OAP_AUTH=\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$(cat \"$SK\u002Foap-demo-env-auth.key\")\\\"}\" \\\n  HORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  HORIZON_AUTH_TOKENS_FILE=\"$SK\u002Fdev-tokens.json\" \\\n  HORIZON_TEMPLATES_MODE=readonly \\\n  node server.js\n```\n\nOpen **`http:\u002F\u002F127.0.0.1:9091`**. One provider renders as a button; two render\nas a themed picker with an arrow to continue.\n\nThings that each cost a debugging cycle:\n\n- **`NODE_USE_ENV_PROXY=1` plus `NO_PROXY`.** Node's `fetch` ignores\n  `http_proxy`, so behind a proxy OIDC discovery fails with\n  `provider_unreachable`. But the proxy also breaks the demo OAP's TLS, so the\n  OAP hosts have to be excluded — you need both, not either.\n- **`HORIZON_PUBLIC_URL` must byte-match a registered redirect URI.** `localhost`\n  and `127.0.0.1` are DIFFERENT registrations, and so is a different port.\n  Register `\u003CpublicUrl>\u002Fapi\u002Fauth\u002Foidc\u002Fcallback`. Google takes a list; GitHub\n  takes up to 10 per OAuth App, so one app can serve dev and prod.\n- **GitHub needs `emailsEndpoint`.** `\u002Fuser` reports `email: null` for any\n  account without a PUBLIC profile address, which is the default. The address\n  lives at `\u002Fuser\u002Femails`, and only entries marked `verified: true` are accepted\n  — Gitee spells verification `state`, so its list cannot be used here at all.\n- **`templates.mode=readonly`** skips the OAP template seed. Drop it to\n  exercise the live template store.\n\nFailures land back on `\u002Flogin?sso_error=\u003Creason>` and the page turns that into a\nsentence; the provider's own words stay in the server log deliberately.\n\n## Boot with the OAuth authorization server (agent login from a CLI)\n\n`oauth.enabled` makes Horizon issue its own tokens, so an MCP client can send\nits operator through the browser instead of being handed one. It is OFF by\ndefault and needs a real secret:\n\n```bash\nHORIZON_OAUTH_ENABLED=true \\\nHORIZON_OAUTH_SIGNING_KEY=\"$(openssl rand -base64 32)\" \\\n  # …plus the SSO boot above\n```\n\n**The key must be 32+ characters.** Anything shorter is treated as no key at\nall: the authorization server stays OFF, its endpoints answer 404, and the boot\nwarning names the length it got. It signs every token, authorization code and\nclient registration, and none of them are stored — so a guessable key mints\nvalid credentials for any user and nothing can tell the difference. A throwaway\nlike `local-test-key` will NOT start it any more.\n\nVerify the whole flow against the real client:\n\n```bash\ncodex -c 'mcp_servers.hz.url=\"http:\u002F\u002F127.0.0.1:9091\u002Fapi\u002Fmcp\"' mcp login hz\n```\n\nIt prints an authorize URL, registers itself dynamically, and after you approve\nthe consent screen reports `Successfully logged in`. The GUI has no OAuth path —\nonly the CLI does — so a desktop client needs an API token instead.\n\n## Boot against a local \u002F remote no-auth OAP\n\nSame recipe, different OAP env vars (no `HORIZON_OAP_AUTH` for a no-auth OAP):\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"; SK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\npkill -f \"tsx watch src\u002Fserver.ts\" 2>\u002Fdev\u002Fnull; pkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\" 2>\u002Fdev\u002Fnull; pkill -f vite 2>\u002Fdev\u002Fnull\nuntil ! lsof -nP -iTCP:8081 -sTCP:LISTEN >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\n\n# LOCAL OAP (defaults already point at 127.0.0.1, so only users are needed):\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n\n# REMOTE no-auth OAP (GraphQL 12800, admin split on 17128):\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=http:\u002F\u002Foap.dev.example:12800 \\\nHORIZON_OAP_ADMIN_URL=http:\u002F\u002Foap.dev.example:17128 \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n\n# UNREACHABLE-OAP landing-block preview (short timeout so errors surface fast):\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=http:\u002F\u002F127.0.0.1:12801 HORIZON_OAP_ADMIN_URL=http:\u002F\u002F127.0.0.1:12801 \\\nHORIZON_OAP_TIMEOUT_MS=4000 \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n```\n\n## Custom ports (two parallel envs)\n\nDefaults are BFF `:8081`, UI `:9091`. To run a second Horizon side-by-side, set\nthe BFF port via **`HORIZON_SERVER_PORT`** (the config's `server.port` token) AND\n**`BFF_PORT`** (Vite's proxy target) to the same value, plus `UI_DEV_PORT`:\n\n```bash\nHORIZON_SERVER_PORT=10081 BFF_PORT=10081 UI_DEV_PORT=10091 \\\n  HORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\n  HORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n( cd \"$REPO\u002Fapps\u002Fui\" && BFF_PORT=10081 UI_DEV_PORT=10091 \\\n    env -u http_proxy -u https_proxy -u all_proxy \\\n        node_modules\u002F.bin\u002Fvite --host 127.0.0.1 & )\n```\n\n**Prod is single-port.** The BFF serves the built UI as static files, so\n`UI_DEV_PORT` is meaningless outside Vite; only `HORIZON_SERVER_PORT` matters.\n\n## Boot the layer \u002F group grant demo (two service groups in one layer)\n\nThe public demo OAP has one service group per layer, so it cannot show a\ngroup-limited role beside a whole-layer one. `rbac-demo\u002F` stands up a local\nOAP (BanyanDB, the e2e-pinned images) with `payments::checkout`,\n`payments::ledger` and `risk::scorer` in GENERAL, the OAP's own metrics in\nSO11Y_OAP (a Platform monitoring layer), and a BFF on **:10083** + Vite on\n**:10093** with one user per grant shape — password == username:\n\n| User | Grant | Sees |\n|---|---|---|\n| `viewer` | built-in | every layer but Platform monitoring; both GENERAL groups |\n| `maintainer` | built-in | every layer, Platform monitoring included |\n| `payments` | `…:read@GENERAL[payments]` | the payments entry of GENERAL only |\n| `risk` | `…:read@GENERAL[risk]` | the risk entry only; its map still names `payments::ledger` as a neighbour |\n| `general` | `…:read@GENERAL` | the whole layer, both entries |\n| `so11y` | `metrics:read@SO11Y_OAP` | that operate layer, without `cluster:read` |\n| `mixed` | metrics on payments, logs on risk, plain `alarms:read` | both entries, metrics on one side only |\n\n```bash\n.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fup.sh     # compose up → BFF → Vite → split GENERAL by group\n.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fdown.sh   # stop both processes, compose down -v\n```\n\n`up.sh` ends by pushing GENERAL's bundled template with `splitByServiceGroup: true` to that OAP, the way the Layer dashboards admin would, so the sidebar shows one entry per group. The first metrics appear a minute or two after the load generator starts. Images come from `test\u002Fe2e\u002Fscript\u002Fenv`; export a variable first to override a pin (`SW_OTEL_COLLECTOR_IMAGE=…`).\n\n## Boot against an LDAP directory (test)\n\nStand up a throwaway OpenLDAP, seed it from `ldap-seed.ldif`, then boot with\n`HORIZON_AUTH_BACKEND=ldap` and the LDAP config from `dev-ldap.json`. Test logins\nmirror the local set (password == username): `admin` → admin, `operator` →\noperator, `maintainer` → maintainer, `viewer` → viewer (`*` fallback). The bind\naccount is `cn=admin,dc=horizon,dc=test` \u002F `admin`.\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"; SK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\ndocker rm -f horizon-ldap 2>\u002Fdev\u002Fnull\ndocker run -d --name horizon-ldap -p 389:389 -p 636:636 \\\n  --env LDAP_ORGANISATION=\"Horizon Test\" --env LDAP_DOMAIN=\"horizon.test\" \\\n  --env LDAP_ADMIN_PASSWORD=\"admin\" osixia\u002Fopenldap:1.5.0\nuntil docker exec horizon-ldap ldapwhoami -x -H ldap:\u002F\u002Flocalhost \\\n  -D \"cn=admin,dc=horizon,dc=test\" -w admin >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\ndocker cp \"$SK\u002Fldap-seed.ldif\" horizon-ldap:\u002Ftmp\u002Fseed.ldif\ndocker exec horizon-ldap ldapadd -x -H ldap:\u002F\u002Flocalhost \\\n  -D \"cn=admin,dc=horizon,dc=test\" -w admin -f \u002Ftmp\u002Fseed.ldif\n\npkill -f \"tsx watch src\u002Fserver.ts\" 2>\u002Fdev\u002Fnull; pkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\" 2>\u002Fdev\u002Fnull\nuntil ! lsof -nP -iTCP:8081 -sTCP:LISTEN >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_AUTH_BACKEND=ldap \\\nHORIZON_AUTH_LDAP=\"$(cat \"$SK\u002Fdev-ldap.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n```\n\n`dev-ldap.json` reads the bind password as the test value `admin`; for a real\ndirectory, edit it (or build the JSON with your own bind password) and never\ncommit a real one. Group resolution runs on the **service bind**, not the user's\ncredentials.\n\n## Verify the BFF is healthy (no browser)\n\n```bash\n# --noproxy so a local proxy (ClashX etc.) doesn't 502 the loopback call.\nuntil curl -s --noproxy '*' -m2 -o \u002Fdev\u002Fnull \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Fauth\u002Fhealth\"; do sleep 1; done\ncurl -s --noproxy '*' -c \u002Ftmp\u002Fsw.cookies -H 'Content-Type: application\u002Fjson' -X POST \\\n  \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Fauth\u002Flogin\" -d '{\"username\":\"admin\",\"password\":\"admin\"}'\n# Expect 200 with {username, roles, verbs, landingRoute}. A 401 \"invalid\n# credentials\" usually means HORIZON_AUTH_LOCAL_USERS wasn't passed (or the\n# wrong HORIZON_CONFIG path \u002F a stale BFF holds the port).\n```\n\n## Editing the dev values\n\n`horizon.yaml` (repo root) is the committed, env-driven config — leave it as-is\nand override via `HORIZON_*` env vars. The dev users \u002F LDAP config live in\n`dev-users.json` \u002F `dev-ldap.json` here (throwaway, single-line JSON). Real\nsecrets stay out of git via the `.claude\u002Fskills\u002Flocal-boot\u002F*.key` rule: the demo\nOAP password in `oap-demo-env-auth.key` and the Bedrock bearer in\n`bedrocks-api.key` are both git-ignored; real LDAP bind passwords are supplied at\nboot. To mint a new local-user hash: `pnpm --filter @skywalking-horizon-ui\u002Fbff cli:hash`.\n","# Boot the Horizon UI local dev env\n\nThere is **one config file**: the repo's committed `horizon.yaml` at the\nrepo root. Every field in it is a `${HORIZON_…:default}` token, so dev boots\nuse the SAME file the Docker image ships and override only what they need via\n**environment variables** — there are no per-scenario config files anymore.\n\nTwo committed helpers live next to this file (throwaway dev values, safe to\ncommit):\n\n- `dev-users.json` — the four local login users (`viewer` \u002F `maintainer` \u002F\n  `operator` \u002F `admin`, **password == username**), as a **single-line** JSON\n  array for `HORIZON_AUTH_LOCAL_USERS`.\n- `dev-ldap.json` — the test-OpenLDAP config for `HORIZON_AUTH_LDAP` (single line).\n\nThe stack: **BFF** (Fastify) on `:8081`, **UI** (Vite) on `:9091` proxying\n`\u002Fapi` → `:8081`. Open **`http:\u002F\u002F127.0.0.1:9091`** (use the IPv4 literal, not\n`localhost` — see the proxy\u002FIPv4 section). Both ports are overridable — see\n\"Custom ports\".\n\n> **JSON env values must be SINGLE-LINE.** `HORIZON_AUTH_LOCAL_USERS`,\n> `HORIZON_OAP_AUTH`, `HORIZON_AUTH_LDAP`, etc. are spliced into the YAML before\n> parsing; a multi-line JSON value breaks the parse (`YAMLParseError: Flow\n> sequence … must be sufficiently indented`). The `dev-*.json` files are already\n> single-line — keep them that way.\n\n## Environment variables (the dev contract)\n\nLocal dev runs as **two processes \u002F two ports**: the BFF (Fastify, owns `\u002Fapi`)\nand Vite (serves the UI, proxies `\u002Fapi` → BFF). The BFF reads `HORIZON_*` via the\nconfig loader's `${VAR:default}` interpolation; Vite reads `BFF_PORT` +\n`UI_DEV_PORT` directly in `apps\u002Fui\u002Fvite.config.ts`.\n\n| Variable                    | Default                    | Used by | Purpose |\n|---|---|---|---|\n| `HORIZON_CONFIG`            | _(none — required)_        | BFF     | **Absolute** path to the config. Always `\"$REPO\u002Fhorizon.yaml\"`. A bare `.\u002Fhorizon.yaml` resolves under `apps\u002Fbff\u002F` — see \"The one gotcha\". |\n| `HORIZON_SERVER_PORT`       | `8081`                     | BFF     | BFF listen port (`server.port`). For a custom port set this AND `BFF_PORT` to the same value. |\n| `BFF_PORT`                  | `8081`                     | UI      | Vite's `\u002Fapi` proxy target. Must match `HORIZON_SERVER_PORT`. |\n| `UI_DEV_PORT`               | `9091`                     | UI      | Vite listen port. Dev-only. |\n| `HORIZON_OAP_QUERY_URL`     | `http:\u002F\u002F127.0.0.1:12800`   | BFF     | OAP GraphQL endpoint. |\n| `HORIZON_OAP_ADMIN_URL`     | `http:\u002F\u002F127.0.0.1:17128`   | BFF     | OAP admin REST endpoint. Often a different port from GraphQL (the demo splits on `:17128`) — if the BFF logs `UITemplate 404`, this is wrong. |\n| `HORIZON_OAP_ZIPKIN_URL`    | `http:\u002F\u002F127.0.0.1:9412\u002Fzipkin` | BFF | Zipkin query endpoint (Zipkin trace layer). |\n| `HORIZON_OAP_TIMEOUT_MS`    | `15000`                    | BFF     | OAP request timeout. Lower it (`4000`) when previewing the \"OAP unreachable\" landing block so errors surface fast. |\n| `HORIZON_OAP_AUTH`          | _(none)_                   | BFF     | OAP basic-auth as JSON, e.g. `{\"username\":\"admin\",\"password\":\"…\"}`. The demo needs it (password from `oap-demo-env-auth.key`). |\n| `HORIZON_AUTH_LOCAL_USERS`  | `[]`                       | BFF     | Local login users (JSON array, single-line). Use `$(cat dev-users.json)`. |\n| `HORIZON_AUTH_TOKENS_FILE`  | _(none)_                   | BFF     | Path to an API-token file — the credential for non-browser callers (scripts, CI, MCP clients). Point it at `\"$SK\u002Fdev-tokens.json\"`, which is **git-ignored and not committed**: mint your own the first time with `pnpm --filter @skywalking-horizon-ui\u002Fbff cli:token admin --label dev`, then paste the printed entry into that file. A working token must never be committed, even a dev one — the repo is public. |\n| `HORIZON_AUTH_BACKEND`      | `local`                    | BFF     | `local` or `ldap`. |\n| `HORIZON_AUTH_LDAP`         | _(none)_                   | BFF     | LDAP config (JSON, single-line) when backend=ldap. Use `$(cat dev-ldap.json)`. |\n| `HORIZON_TEMPLATES_MODE`    | `live`                     | BFF     | `live` (seed + read ui_template) or `readonly` (render the bundle, config read-only). |\n\nRBAC is left to the built-in role defaults (the `horizon.yaml` token\n`roles: ${HORIZON_RBAC_ROLES:null}` falls through to them), so no roles env var\nis needed for dev.\n\n## The one gotcha that bites every time\n\nThe BFF dev script is `tsx watch src\u002Fserver.ts` and pnpm runs it with **cwd =\n`apps\u002Fbff`**. The config path defaults to `.\u002Fhorizon.yaml`, resolved relative to\ncwd — so a bare `.\u002Fhorizon.yaml` points at the non-existent `apps\u002Fbff\u002Fhorizon.yaml`\n(NOT the repo-root one), and the loader silently falls back to schema defaults\nwith **zero users** (every login then fails \"invalid credentials\").\n\n**Always pass `HORIZON_CONFIG` as an ABSOLUTE path:** `\"$REPO\u002Fhorizon.yaml\"`.\n\n## Proxy + IPv4 (the second gotcha)\n\nTwo things make the UI look \"not accessible\" even when Vite is running:\n\n- **Vite binds IPv6 `[::1]` by default**, so `127.0.0.1:9091` (IPv4) has nothing and many browsers \u002F curl fail. **Force IPv4** with `--host 127.0.0.1`. Note `pnpm --filter ui run dev -- --host …` does NOT forward the flag — run the Vite binary directly (`apps\u002Fui\u002Fnode_modules\u002F.bin\u002Fvite --host 127.0.0.1`).\n- **A local proxy** (ClashX \u002F v2ray etc. — `http_proxy` \u002F `https_proxy` \u002F `all_proxy` pointing at `127.0.0.1:\u003Cport>`) intercepts loopback and returns `502`. Detect and bypass it for the dev hosts.\n\nDetect a local proxy before booting:\n```bash\nenv | grep -iE '^(http_proxy|https_proxy|all_proxy)=' && echo \"local proxy detected — will bypass loopback\"\n```\n\nThe browser uses its OWN proxy settings (not the shell's), so the developer must also let `127.0.0.1` \u002F `localhost` go direct (ClashX \"bypass localhost\" \u002F system proxy no-proxy list). The env-level bypass below only fixes CLI tools and Vite's own fetches.\n\n## The stale-process trap (why a config switch \"didn't take\")\n\n`tsx watch` keeps the old BFF alive, so a freshly launched BFF silently dies on `EADDRINUSE: 127.0.0.1:8081` while the OLD process keeps serving the OLD env. Symptom: you switch demo↔local, everything looks fine, but the UI still shows the previous OAP's data.\n\n- `pkill -f \"tsx watch src\u002Fserver.ts\"` may miss the actual listener — also `pkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\"`, and **verify the port is free with `lsof` before relaunching** (loop until free; the watcher respawns a child).\n- After boot, **confirm which OAP the LIVE process uses** — don't trust that your new process won the port:\n  ```bash\n  curl -s --noproxy '*' -b \u002Ftmp\u002Fsw.cookies \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Foap\u002Fconfig\" | grep -oE '\"adminUrl\":\"[^\"]*\"'\n  # local => http:\u002F\u002F127.0.0.1:17128 ; demo => https:\u002F\u002Fdemo.skywalking.apache.org:17128\n  ```\n\n## Boot against the public demo OAP\n\nThe demo OAP needs basic-auth (network username `admin`). The password is NOT\ncommitted — it lives in `oap-demo-env-auth.key` next to this file (git-ignored via\nthe `.claude\u002Fskills\u002Flocal-boot\u002F*.key` rule). Source it; if missing, ask the developer and\nrecreate it (one line, the password only).\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"\nSECRET=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\u002Foap-demo-env-auth.key\"\nif [ -s \"$SECRET\" ]; then\n  OAP_PASSWORD=\"$(cat \"$SECRET\")\"; export OAP_PASSWORD\nelse\n  read -rsp \"Demo OAP password: \" OAP_PASSWORD && export OAP_PASSWORD && echo\n  printf '%s\\n' \"$OAP_PASSWORD\" > \"$SECRET\" && chmod 600 \"$SECRET\"  # cache for next boot\nfi\n\n# Kill prior dev servers + confirm the port is free (see stale-process trap).\npkill -f \"tsx watch src\u002Fserver.ts\" 2>\u002Fdev\u002Fnull\npkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\" 2>\u002Fdev\u002Fnull; pkill -f vite 2>\u002Fdev\u002Fnull\nuntil ! lsof -nP -iTCP:8081 -sTCP:LISTEN >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\n\n# BFF — repo horizon.yaml + everything via env. JSON values are single-line.\nSK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=https:\u002F\u002Fdemo.skywalking.apache.org:12800 \\\nHORIZON_OAP_ADMIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:17128 \\\nHORIZON_OAP_ZIPKIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:9412\u002Fzipkin \\\nHORIZON_OAP_AUTH=\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$OAP_PASSWORD\\\"}\" \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\nHORIZON_AUTH_TOKENS_FILE=\"$SK\u002Fdev-tokens.json\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n\n# UI — IPv4 host + loopback proxy bypass (run the binary directly so --host applies).\n( cd \"$REPO\u002Fapps\u002Fui\" && \\\n  env -u http_proxy -u https_proxy -u all_proxy -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY \\\n      no_proxy=\"localhost,127.0.0.1,::1\" NO_PROXY=\"localhost,127.0.0.1,::1\" \\\n      node_modules\u002F.bin\u002Fvite --host 127.0.0.1 & )\n```\n\nThen open **`http:\u002F\u002F127.0.0.1:9091`** and log in as `admin` \u002F `admin`. To boot in\nread-only template mode, add `HORIZON_TEMPLATES_MODE=readonly` to the BFF line.\n\n## Boot with the AI assistant enabled (Bedrock \u002F DeepSeek)\n\nThe AI assistant (the `ai:` block in `horizon.yaml`) is **off by default** — the\nlauncher stays hidden until the feature is enabled AND a usable provider is\nconfigured. To exercise it in dev, add the `HORIZON_AI_*` env vars below to any\nboot above — usually the **demo** boot, so there is live data to investigate.\n\nThe dev provider is **Amazon Bedrock** running **DeepSeek** (`deepseek.v3.2`,\nregion `us-west-2`). The Bedrock key is a secret kept next to this file:\n\n- `bedrocks-api.key` — a Bedrock **`ABSK…` bearer token**, one line, git-ignored\n  via the `.claude\u002Fskills\u002Flocal-boot\u002F*.key` rule (same rule as the OAP password).\n  If missing, mint one in the AWS console (Bedrock → API keys) and drop it here.\n\nOur config field is **`HORIZON_AI_API_KEY`** — the BFF passes it to the SDK\nexplicitly as `bedrockBearerToken`. Do **NOT** set `AWS_BEARER_TOKEN_BEDROCK`:\nthat is the AWS SDK's own env var, which our code deliberately bypasses so\nconcurrent requests stay isolated. The **only bedrock-specific\nextra is `HORIZON_AI_REGION`** (it falls back to `AWS_REGION` when blank). Our\nbedrock path REQUIRES the bearer key and does **not** use the AWS SSO \u002F IAM\ncredential chain — a missing key is a clean 503, not an SSO prompt.\n\n| Variable                    | Value (dev)               | Purpose |\n|---|---|---|\n| `HORIZON_AI_ENABLED`        | `true`                    | Master switch (default `false`). |\n| `HORIZON_AI_PROVIDER`       | `bedrock`                 | Transport — `openai-compatible` (default) or `bedrock`. |\n| `HORIZON_AI_MODEL`          | `deepseek.v3.2`           | Bedrock model \u002F inference-profile id. |\n| `HORIZON_AI_REGION`         | `us-west-2`               | Bedrock-only extra; falls back to `AWS_REGION`. |\n| `HORIZON_AI_API_KEY`        | `$(cat bedrocks-api.key)` | **Secret** `ABSK` bearer. Redacted from logs. |\n\nAdd these lines to the demo boot's BFF invocation (keep the SECRET \u002F pkill \u002F\nport-free steps from the demo section):\n\n```bash\nSK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=https:\u002F\u002Fdemo.skywalking.apache.org:12800 \\\nHORIZON_OAP_ADMIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:17128 \\\nHORIZON_OAP_ZIPKIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:9412\u002Fzipkin \\\nHORIZON_OAP_AUTH=\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$OAP_PASSWORD\\\"}\" \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\nHORIZON_AI_ENABLED=true \\\nHORIZON_AI_PROVIDER=bedrock \\\nHORIZON_AI_MODEL=deepseek.v3.2 \\\nHORIZON_AI_REGION=us-west-2 \\\nHORIZON_AI_API_KEY=\"$(cat \"$SK\u002Fbedrocks-api.key\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n```\n\nVerify readiness after login — expect `ready:true`:\n```bash\ncurl -s --noproxy '*' -b \u002Ftmp\u002Fsw.cookies \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Fai\u002Fconfig\"\n```\nThen the floating **AI Assistant** launcher appears on the right edge; the chat\nstreams an answer with inline figures (open `\u002Fai` for the full page). **On-demand\npod logs** work when the OAP itself runs in Kubernetes (the public demo does) and\nits `enableOnDemandPodLog` is on — the assistant's `fetch_pod_logs` tool and the\nper-layer Pod Logs tab both read them live.\n\n## Boot with single sign-on (Google and\u002For GitHub)\n\nHorizon can hand the login to identity providers (`auth.sso`). The local dev\nconfig is split three ways, mirroring the split the config schema is heading\ntoward — **a provider says how to authenticate; roles say what you get, and are\nnot per-provider**:\n\n| File | Holds |\n|---|---|\n| `gmail_oauth.config` | Google provider: client id\u002Fsecret + endpoints. Connection only. |\n| `github_oauth.config` | GitHub provider: client id\u002Fsecret + endpoints, `namePath: login`, `emailsEndpoint`. Connection only. |\n| `oauth.config` | ONE role table for every provider: `defaultRoles`, `roleByEmail`, `roleByDomain`. Goes into `auth.sso.roles` verbatim. |\n\nAll three are **git-ignored and must never be committed**: this directory is\ndeny-by-default in `.gitignore`, with only SKILL.md, `dev-users.json`,\n`dev-ldap.json` and `ldap-seed.ldif` allow-listed.\n\n**Why one role table.** Roles resolve from the EMAIL ADDRESS alone — a token\ncarries no provider — so a per-provider role table is a promise the architecture\ncannot keep. Keeping the addresses in one file also avoids the failure that\ncost a debugging session: two providers whose tables disagreed about the same\naddress once resolved to NO roles, and an API token with no roles is refused,\nso adding a second provider logged every agent out with an unexplained 401.\n\n**Use the PACKAGED build, on ONE port.** The dev BFF is API-only, so the\npost-login redirect lands on an SPA route it does not serve and you get a 404\nthat looks like a login failure. `dist\u002Fserver.js` serves the UI and the API\ntogether, exactly as a real deployment does.\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"; SK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\npnpm package                       # if dist\u002F is stale\n\n# Compose the providers with the shared role table. Drop either provider from\n# the list to boot with just one.\nexport HORIZON_AUTH_SSO=$(python3 -c \"\nimport json\nroles = json.load(open('$SK\u002Foauth.config'))\nprov = lambda f: json.load(open(f))['horizon']\nprint(json.dumps({\n  'providers': [prov('$SK\u002Fgmail_oauth.config'), prov('$SK\u002Fgithub_oauth.config')],\n  'roles': {k: roles[k] for k in ('defaultRoles', 'roleByEmail', 'roleByDomain') if k in roles},\n}))\")\n\ncd \"$REPO\u002Fdist\" && NODE_USE_ENV_PROXY=1 \\\n  NO_PROXY=\"demo.skywalking.apache.org,127.0.0.1,localhost,::1\" \\\n  HORIZON_CONFIG=.\u002Fhorizon.yaml \\\n  HORIZON_SERVER_HOST=127.0.0.1 HORIZON_SERVER_PORT=9091 \\\n  HORIZON_PUBLIC_URL=http:\u002F\u002F127.0.0.1:9091 \\\n  HORIZON_OAP_QUERY_URL=https:\u002F\u002Fdemo.skywalking.apache.org:12800 \\\n  HORIZON_OAP_ADMIN_URL=https:\u002F\u002Fdemo.skywalking.apache.org:17128 \\\n  HORIZON_OAP_AUTH=\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$(cat \"$SK\u002Foap-demo-env-auth.key\")\\\"}\" \\\n  HORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  HORIZON_AUTH_TOKENS_FILE=\"$SK\u002Fdev-tokens.json\" \\\n  HORIZON_TEMPLATES_MODE=readonly \\\n  node server.js\n```\n\nOpen **`http:\u002F\u002F127.0.0.1:9091`**. One provider renders as a button; two render\nas a themed picker with an arrow to continue.\n\nThings that each cost a debugging cycle:\n\n- **`NODE_USE_ENV_PROXY=1` plus `NO_PROXY`.** Node's `fetch` ignores\n  `http_proxy`, so behind a proxy OIDC discovery fails with\n  `provider_unreachable`. But the proxy also breaks the demo OAP's TLS, so the\n  OAP hosts have to be excluded — you need both, not either.\n- **`HORIZON_PUBLIC_URL` must byte-match a registered redirect URI.** `localhost`\n  and `127.0.0.1` are DIFFERENT registrations, and so is a different port.\n  Register `\u003CpublicUrl>\u002Fapi\u002Fauth\u002Foidc\u002Fcallback`. Google takes a list; GitHub\n  takes up to 10 per OAuth App, so one app can serve dev and prod.\n- **GitHub needs `emailsEndpoint`.** `\u002Fuser` reports `email: null` for any\n  account without a PUBLIC profile address, which is the default. The address\n  lives at `\u002Fuser\u002Femails`, and only entries marked `verified: true` are accepted\n  — Gitee spells verification `state`, so its list cannot be used here at all.\n- **`templates.mode=readonly`** skips the OAP template seed. Drop it to\n  exercise the live template store.\n\nFailures land back on `\u002Flogin?sso_error=\u003Creason>` and the page turns that into a\nsentence; the provider's own words stay in the server log deliberately.\n\n## Boot with the OAuth authorization server (agent login from a CLI)\n\n`oauth.enabled` makes Horizon issue its own tokens, so an MCP client can send\nits operator through the browser instead of being handed one. It is OFF by\ndefault and needs a real secret:\n\n```bash\nHORIZON_OAUTH_ENABLED=true \\\nHORIZON_OAUTH_SIGNING_KEY=\"$(openssl rand -base64 32)\" \\\n  # …plus the SSO boot above\n```\n\n**The key must be 32+ characters.** Anything shorter is treated as no key at\nall: the authorization server stays OFF, its endpoints answer 404, and the boot\nwarning names the length it got. It signs every token, authorization code and\nclient registration, and none of them are stored — so a guessable key mints\nvalid credentials for any user and nothing can tell the difference. A throwaway\nlike `local-test-key` will NOT start it any more.\n\nVerify the whole flow against the real client:\n\n```bash\ncodex -c 'mcp_servers.hz.url=\"http:\u002F\u002F127.0.0.1:9091\u002Fapi\u002Fmcp\"' mcp login hz\n```\n\nIt prints an authorize URL, registers itself dynamically, and after you approve\nthe consent screen reports `Successfully logged in`. The GUI has no OAuth path —\nonly the CLI does — so a desktop client needs an API token instead.\n\n## Boot against a local \u002F remote no-auth OAP\n\nSame recipe, different OAP env vars (no `HORIZON_OAP_AUTH` for a no-auth OAP):\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"; SK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\npkill -f \"tsx watch src\u002Fserver.ts\" 2>\u002Fdev\u002Fnull; pkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\" 2>\u002Fdev\u002Fnull; pkill -f vite 2>\u002Fdev\u002Fnull\nuntil ! lsof -nP -iTCP:8081 -sTCP:LISTEN >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\n\n# LOCAL OAP (defaults already point at 127.0.0.1, so only users are needed):\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n\n# REMOTE no-auth OAP (GraphQL 12800, admin split on 17128):\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=http:\u002F\u002Foap.dev.example:12800 \\\nHORIZON_OAP_ADMIN_URL=http:\u002F\u002Foap.dev.example:17128 \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n\n# UNREACHABLE-OAP landing-block preview (short timeout so errors surface fast):\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_OAP_QUERY_URL=http:\u002F\u002F127.0.0.1:12801 HORIZON_OAP_ADMIN_URL=http:\u002F\u002F127.0.0.1:12801 \\\nHORIZON_OAP_TIMEOUT_MS=4000 \\\nHORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n```\n\n## Custom ports (two parallel envs)\n\nDefaults are BFF `:8081`, UI `:9091`. To run a second Horizon side-by-side, set\nthe BFF port via **`HORIZON_SERVER_PORT`** (the config's `server.port` token) AND\n**`BFF_PORT`** (Vite's proxy target) to the same value, plus `UI_DEV_PORT`:\n\n```bash\nHORIZON_SERVER_PORT=10081 BFF_PORT=10081 UI_DEV_PORT=10091 \\\n  HORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\n  HORIZON_AUTH_LOCAL_USERS=\"$(cat \"$SK\u002Fdev-users.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n( cd \"$REPO\u002Fapps\u002Fui\" && BFF_PORT=10081 UI_DEV_PORT=10091 \\\n    env -u http_proxy -u https_proxy -u all_proxy \\\n        node_modules\u002F.bin\u002Fvite --host 127.0.0.1 & )\n```\n\n**Prod is single-port.** The BFF serves the built UI as static files, so\n`UI_DEV_PORT` is meaningless outside Vite; only `HORIZON_SERVER_PORT` matters.\n\n## Boot the layer \u002F group grant demo (two service groups in one layer)\n\nThe public demo OAP has one service group per layer, so it cannot show a\ngroup-limited role beside a whole-layer one. `rbac-demo\u002F` stands up a local\nOAP (BanyanDB, the e2e-pinned images) with `payments::checkout`,\n`payments::ledger` and `risk::scorer` in GENERAL, the OAP's own metrics in\nSO11Y_OAP (a Platform monitoring layer), and a BFF on **:10083** + Vite on\n**:10093** with one user per grant shape — password == username:\n\n| User | Grant | Sees |\n|---|---|---|\n| `viewer` | built-in | every layer but Platform monitoring; both GENERAL groups |\n| `maintainer` | built-in | every layer, Platform monitoring included |\n| `payments` | `…:read@GENERAL[payments]` | the payments entry of GENERAL only |\n| `risk` | `…:read@GENERAL[risk]` | the risk entry only; its map still names `payments::ledger` as a neighbour |\n| `general` | `…:read@GENERAL` | the whole layer, both entries |\n| `so11y` | `metrics:read@SO11Y_OAP` | that operate layer, without `cluster:read` |\n| `mixed` | metrics on payments, logs on risk, plain `alarms:read` | both entries, metrics on one side only |\n\n```bash\n.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fup.sh     # compose up → BFF → Vite → split GENERAL by group\n.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fdown.sh   # stop both processes, compose down -v\n```\n\n`up.sh` ends by pushing GENERAL's bundled template with `splitByServiceGroup: true` to that OAP, the way the Layer dashboards admin would, so the sidebar shows one entry per group. The first metrics appear a minute or two after the load generator starts. Images come from `test\u002Fe2e\u002Fscript\u002Fenv`; export a variable first to override a pin (`SW_OTEL_COLLECTOR_IMAGE=…`).\n\n## Boot against an LDAP directory (test)\n\nStand up a throwaway OpenLDAP, seed it from `ldap-seed.ldif`, then boot with\n`HORIZON_AUTH_BACKEND=ldap` and the LDAP config from `dev-ldap.json`. Test logins\nmirror the local set (password == username): `admin` → admin, `operator` →\noperator, `maintainer` → maintainer, `viewer` → viewer (`*` fallback). The bind\naccount is `cn=admin,dc=horizon,dc=test` \u002F `admin`.\n\n```bash\nREPO=\"$(git rev-parse --show-toplevel)\"; SK=\"$REPO\u002F.claude\u002Fskills\u002Flocal-boot\"\ndocker rm -f horizon-ldap 2>\u002Fdev\u002Fnull\ndocker run -d --name horizon-ldap -p 389:389 -p 636:636 \\\n  --env LDAP_ORGANISATION=\"Horizon Test\" --env LDAP_DOMAIN=\"horizon.test\" \\\n  --env LDAP_ADMIN_PASSWORD=\"admin\" osixia\u002Fopenldap:1.5.0\nuntil docker exec horizon-ldap ldapwhoami -x -H ldap:\u002F\u002Flocalhost \\\n  -D \"cn=admin,dc=horizon,dc=test\" -w admin >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\ndocker cp \"$SK\u002Fldap-seed.ldif\" horizon-ldap:\u002Ftmp\u002Fseed.ldif\ndocker exec horizon-ldap ldapadd -x -H ldap:\u002F\u002Flocalhost \\\n  -D \"cn=admin,dc=horizon,dc=test\" -w admin -f \u002Ftmp\u002Fseed.ldif\n\npkill -f \"tsx watch src\u002Fserver.ts\" 2>\u002Fdev\u002Fnull; pkill -f \"tsx\u002Fdist\u002Fcli.mjs watch\" 2>\u002Fdev\u002Fnull\nuntil ! lsof -nP -iTCP:8081 -sTCP:LISTEN >\u002Fdev\u002Fnull 2>&1; do sleep 1; done\nHORIZON_CONFIG=\"$REPO\u002Fhorizon.yaml\" \\\nHORIZON_AUTH_BACKEND=ldap \\\nHORIZON_AUTH_LDAP=\"$(cat \"$SK\u002Fdev-ldap.json\")\" \\\n  pnpm --filter @skywalking-horizon-ui\u002Fbff run dev &\n```\n\n`dev-ldap.json` reads the bind password as the test value `admin`; for a real\ndirectory, edit it (or build the JSON with your own bind password) and never\ncommit a real one. Group resolution runs on the **service bind**, not the user's\ncredentials.\n\n## Verify the BFF is healthy (no browser)\n\n```bash\n# --noproxy so a local proxy (ClashX etc.) doesn't 502 the loopback call.\nuntil curl -s --noproxy '*' -m2 -o \u002Fdev\u002Fnull \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Fauth\u002Fhealth\"; do sleep 1; done\ncurl -s --noproxy '*' -c \u002Ftmp\u002Fsw.cookies -H 'Content-Type: application\u002Fjson' -X POST \\\n  \"http:\u002F\u002F127.0.0.1:8081\u002Fapi\u002Fauth\u002Flogin\" -d '{\"username\":\"admin\",\"password\":\"admin\"}'\n# Expect 200 with {username, roles, verbs, landingRoute}. A 401 \"invalid\n# credentials\" usually means HORIZON_AUTH_LOCAL_USERS wasn't passed (or the\n# wrong HORIZON_CONFIG path \u002F a stale BFF holds the port).\n```\n\n## Editing the dev values\n\n`horizon.yaml` (repo root) is the committed, env-driven config — leave it as-is\nand override via `HORIZON_*` env vars. The dev users \u002F LDAP config live in\n`dev-users.json` \u002F `dev-ldap.json` here (throwaway, single-line JSON). Real\nsecrets stay out of git via the `.claude\u002Fskills\u002Flocal-boot\u002F*.key` rule: the demo\nOAP password in `oap-demo-env-auth.key` and the Bedrock bearer in\n`bedrocks-api.key` are both git-ignored; real LDAP bind passwords are supplied at\nboot. To mint a new local-user hash: `pnpm --filter @skywalking-horizon-ui\u002Fbff cli:hash`.\n",{"name":5,"description":7,"user-invocable":33},true,"main","e5e3bbc552ddcc65d15221621d94012f2eee19df",".claude\u002Fskills\u002Flocal-boot",10,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui","https:\u002F\u002Fskywalking.apache.org\u002F","https:\u002F\u002Fgithub.com\u002Fapache","https:\u002F\u002Fwww.apache.org\u002F","2026-11-11 11:55:13",{"source":8,"skillName":5,"commands":44,"prompt":54,"zipAvailable":33},[45,48,51],{"tool":46,"command":47},"npx","npx skills add apache\u002Fskywalking-horizon-ui --skill local-boot",{"tool":49,"command":50},"bunx","bunx skills add apache\u002Fskywalking-horizon-ui --skill local-boot",{"tool":52,"command":53},"pnpm","pnpm dlx skills add apache\u002Fskywalking-horizon-ui --skill local-boot","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002FSKILL.md",[56,62,66,72,76,80,84,88,92,96,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,245,249,253,257,261,265,269,273,277,281,285,289,293,297,301,305,309,313,317,321,325,329,333,337,341,345,349,353,359,363,367,371,375,379,383,387,392,396,400,404,408,412,416,420,424,428,432,436,440,444,448,452,456,460,464,468,472,476,480,484,488,492,496,500,504,508,512,516,520,524,528,532,536,540,544,548,552,556,560,564,568,572,576,580,584,588,592,596,600,604,608,612,616,620,624,628,632,636,640,644,648,652,656,660,664,668,672,676,680,684,688,692,696,700,704,708,712,716,720,724,728,732,736,740,744,748,752,756,760,764,768,772,776,780,784,788,792,796,800,804,808,812,816,820,824],{"path":57,"resourceType":58,"resourceTypeDesc":59,"sizeBytes":60,"sourceHtmlUrl":61},"assets\u002FJetBrainsMono-OFL.txt","ASSET","资产文件",4398,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fassets\u002FJetBrainsMono-OFL.txt",{"path":63,"resourceType":58,"resourceTypeDesc":59,"sizeBytes":64,"sourceHtmlUrl":65},"assets\u002Ftemplate.html",787334,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fassets\u002Ftemplate.html",{"path":67,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":71},"bin\u002Farchify.mjs","SCRIPT","脚本",288781,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Farchify.mjs",{"path":73,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":74,"sourceHtmlUrl":75},"bin\u002Fdelivery-update.mjs",3700,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Fdelivery-update.mjs",{"path":77,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":78,"sourceHtmlUrl":79},"bin\u002Ffinalize.mjs",50052,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Ffinalize.mjs",{"path":81,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":82,"sourceHtmlUrl":83},"bin\u002Fopen-artifact.mjs",4144,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Fopen-artifact.mjs",{"path":85,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":86,"sourceHtmlUrl":87},"bin\u002Fpreview.mjs",36668,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Fpreview.mjs",{"path":89,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":90,"sourceHtmlUrl":91},"bin\u002Frecover-output.mjs",1367,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Frecover-output.mjs",{"path":93,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":94,"sourceHtmlUrl":95},"bin\u002Fvisual-check.mjs",120537,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbin\u002Fvisual-check.mjs",{"path":97,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":100,"sourceHtmlUrl":101},"brand-marks\u002Fcatalog.json","REFERENCE","参考文档",14162,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbrand-marks\u002Fcatalog.json",{"path":103,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":104,"sourceHtmlUrl":105},"brand-marks\u002FREADME.md",1449,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fbrand-marks\u002FREADME.md",{"path":107,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":108,"sourceHtmlUrl":109},"delta\u002Farchitecture-delta.mjs",79087,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fdelta\u002Farchitecture-delta.mjs",{"path":111,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":112,"sourceHtmlUrl":113},"dev-ldap.json",581,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Fdev-ldap.json",{"path":115,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":116,"sourceHtmlUrl":117},"dev-users.json",636,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Fdev-users.json",{"path":119,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":120,"sourceHtmlUrl":121},"examples\u002Fagent-run.lifecycle.json",3260,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fagent-run.lifecycle.json",{"path":123,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":124,"sourceHtmlUrl":125},"examples\u002Fagent-tool-call.workflow.json",4939,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fagent-tool-call.workflow.json",{"path":127,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":128,"sourceHtmlUrl":129},"examples\u002Farchify-dev-activity.timeline.json",4460,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Farchify-dev-activity.timeline.json",{"path":131,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":132,"sourceHtmlUrl":133},"examples\u002Farchify-repository.tree.json",4368,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Farchify-repository.tree.json",{"path":135,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":136,"sourceHtmlUrl":137},"examples\u002Fasync-job-roundtrip.sequence.json",3766,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fasync-job-roundtrip.sequence.json",{"path":139,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":140,"sourceHtmlUrl":141},"examples\u002Fbrand-aware-delivery.architecture.json",2789,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fbrand-aware-delivery.architecture.json",{"path":143,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":144,"sourceHtmlUrl":145},"examples\u002Fcache-miss-request.sequence.json",3805,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fcache-miss-request.sequence.json",{"path":147,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":148,"sourceHtmlUrl":149},"examples\u002Fcheckout-platform.base.architecture.json",2279,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fcheckout-platform.base.architecture.json",{"path":151,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":152,"sourceHtmlUrl":153},"examples\u002Fcheckout-platform.head.architecture.json",2413,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fcheckout-platform.head.architecture.json",{"path":155,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":156,"sourceHtmlUrl":157},"examples\u002Fcheckout-request.waterfall.json",1209,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fcheckout-request.waterfall.json",{"path":159,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":160,"sourceHtmlUrl":161},"examples\u002Fclass-payment-processors-rendered.html",875036,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fclass-payment-processors-rendered.html",{"path":163,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":164,"sourceHtmlUrl":165},"examples\u002Fclass-payments-rendered.html",840775,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fclass-payments-rendered.html",{"path":167,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":168,"sourceHtmlUrl":169},"examples\u002Fdataflow-product-analytics.html",843855,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fdataflow-product-analytics.html",{"path":171,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":172,"sourceHtmlUrl":173},"examples\u002Fdelivery.explainer.json",4570,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fdelivery.explainer.json",{"path":175,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":176,"sourceHtmlUrl":177},"examples\u002Fdeployment-release.lifecycle.json",4155,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fdeployment-release.lifecycle.json",{"path":179,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":180,"sourceHtmlUrl":181},"examples\u002Ferd-orders-rendered.html",861259,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Ferd-orders-rendered.html",{"path":183,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":184,"sourceHtmlUrl":185},"examples\u002Fevent-stream.dataflow.json",4769,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fevent-stream.dataflow.json",{"path":187,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":188,"sourceHtmlUrl":189},"examples\u002Fexample-rebuild.waterfall.json",4617,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fexample-rebuild.waterfall.json",{"path":191,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":192,"sourceHtmlUrl":193},"examples\u002Fholiday-planning.workflow.json",3019,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fholiday-planning.workflow.json",{"path":195,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":196,"sourceHtmlUrl":197},"examples\u002Fincident-response.workflow.json",4723,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fincident-response.workflow.json",{"path":199,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":200,"sourceHtmlUrl":201},"examples\u002Flifecycle-agent-run.html",847663,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flifecycle-agent-run.html",{"path":203,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":204,"sourceHtmlUrl":205},"examples\u002Flocales\u002Fde.json",28444,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Fde.json",{"path":207,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":208,"sourceHtmlUrl":209},"examples\u002Flocales\u002Ffr.json",29281,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Ffr.json",{"path":211,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":212,"sourceHtmlUrl":213},"examples\u002Flocales\u002Ffr.partial.json",959,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Ffr.partial.json",{"path":215,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":216,"sourceHtmlUrl":217},"examples\u002Flocales\u002Fit.json",28793,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Fit.json",{"path":219,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":220,"sourceHtmlUrl":221},"examples\u002Flocales\u002Fja.json",32495,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Fja.json",{"path":223,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":224,"sourceHtmlUrl":225},"examples\u002Flocales\u002Fpt.json",28454,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Fpt.json",{"path":227,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":228,"sourceHtmlUrl":229},"examples\u002Flocales\u002Fru.json",36940,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Flocales\u002Fru.json",{"path":231,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":232,"sourceHtmlUrl":233},"examples\u002Forders.erd.json",7321,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Forders.erd.json",{"path":235,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":236,"sourceHtmlUrl":237},"examples\u002Fpayment-incident.timeline.json",1445,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fpayment-incident.timeline.json",{"path":239,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":240,"sourceHtmlUrl":241},"examples\u002Fpayment-platform.tree.json",1214,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fpayment-platform.tree.json",{"path":243,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":232,"sourceHtmlUrl":244},"examples\u002Fpayment-processors.class.json","https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fpayment-processors.class.json",{"path":246,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":247,"sourceHtmlUrl":248},"examples\u002Fpayments.class.json",2828,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fpayments.class.json",{"path":250,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":251,"sourceHtmlUrl":252},"examples\u002Fproduct-analytics.dataflow.json",5035,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fproduct-analytics.dataflow.json",{"path":254,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":255,"sourceHtmlUrl":256},"examples\u002Fproduction-deployment.architecture.json",4734,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fproduction-deployment.architecture.json",{"path":258,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":259,"sourceHtmlUrl":260},"examples\u002Frelease-delivery.workflow.json",4510,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Frelease-delivery.workflow.json",{"path":262,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":263,"sourceHtmlUrl":264},"examples\u002Fsequence-cache-miss-request.html",841568,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fsequence-cache-miss-request.html",{"path":266,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":267,"sourceHtmlUrl":268},"examples\u002Fsubscription-billing-rendered.html",884212,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fsubscription-billing-rendered.html",{"path":270,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":271,"sourceHtmlUrl":272},"examples\u002Fsubscription-billing.erd.json",11817,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fsubscription-billing.erd.json",{"path":274,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":275,"sourceHtmlUrl":276},"examples\u002Ftimeline-archify-dev-activity-rendered.html",866510,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Ftimeline-archify-dev-activity-rendered.html",{"path":278,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":279,"sourceHtmlUrl":280},"examples\u002Ftimeline-payment-incident-rendered.html",834097,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Ftimeline-payment-incident-rendered.html",{"path":282,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":283,"sourceHtmlUrl":284},"examples\u002Ftree-archify-repository-rendered.html",877360,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Ftree-archify-repository-rendered.html",{"path":286,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":287,"sourceHtmlUrl":288},"examples\u002Ftree-payment-platform-rendered.html",839719,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Ftree-payment-platform-rendered.html",{"path":290,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":291,"sourceHtmlUrl":292},"examples\u002Fwaterfall-checkout-request-rendered.html",833386,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fwaterfall-checkout-request-rendered.html",{"path":294,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":295,"sourceHtmlUrl":296},"examples\u002Fwaterfall-example-rebuild-rendered.html",863204,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fwaterfall-example-rebuild-rendered.html",{"path":298,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":299,"sourceHtmlUrl":300},"examples\u002Fweb-app-rendered.html",846197,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fweb-app-rendered.html",{"path":302,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":303,"sourceHtmlUrl":304},"examples\u002Fweb-app.architecture.json",3197,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fweb-app.architecture.json",{"path":306,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":307,"sourceHtmlUrl":308},"examples\u002Fworkflow-agent-tool-call-rendered.html",851280,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexamples\u002Fworkflow-agent-tool-call-rendered.html",{"path":310,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":311,"sourceHtmlUrl":312},"explainer\u002Fbrowser-check.mjs",30708,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fbrowser-check.mjs",{"path":314,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":315,"sourceHtmlUrl":316},"explainer\u002Fcharts.mjs",5997,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fcharts.mjs",{"path":318,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":319,"sourceHtmlUrl":320},"explainer\u002Fcheck.mjs",14888,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fcheck.mjs",{"path":322,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":323,"sourceHtmlUrl":324},"explainer\u002Fdiagrams.mjs",38710,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fdiagrams.mjs",{"path":326,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":327,"sourceHtmlUrl":328},"explainer\u002Fdiff.mjs",8454,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fdiff.mjs",{"path":330,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":331,"sourceHtmlUrl":332},"explainer\u002Finline.mjs",8721,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Finline.mjs",{"path":334,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":335,"sourceHtmlUrl":336},"explainer\u002Flayout.mjs",2571,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Flayout.mjs",{"path":338,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":339,"sourceHtmlUrl":340},"explainer\u002Fpage-bundle.mjs",1138,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fpage-bundle.mjs",{"path":342,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":343,"sourceHtmlUrl":344},"explainer\u002Fparse.mjs",27256,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fparse.mjs",{"path":346,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":347,"sourceHtmlUrl":348},"explainer\u002Fpatch.mjs",12039,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fpatch.mjs",{"path":350,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":351,"sourceHtmlUrl":352},"explainer\u002Fprepare.mjs",9819,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fprepare.mjs",{"path":354,"resourceType":355,"resourceTypeDesc":356,"sizeBytes":357,"sourceHtmlUrl":358},"explainer\u002Freader.css","OTHER","其他",47157,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Freader.css",{"path":360,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":361,"sourceHtmlUrl":362},"explainer\u002Freader.js",51676,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Freader.js",{"path":364,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":365,"sourceHtmlUrl":366},"explainer\u002Frender.mjs",34005,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Frender.mjs",{"path":368,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":369,"sourceHtmlUrl":370},"explainer\u002Frevision.mjs",1965,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Frevision.mjs",{"path":372,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":373,"sourceHtmlUrl":374},"explainer\u002Fsources.mjs",20882,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fsources.mjs",{"path":376,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":377,"sourceHtmlUrl":378},"explainer\u002Fvalidate.mjs",14520,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fvalidate.mjs",{"path":380,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":381,"sourceHtmlUrl":382},"explainer\u002Fwriting.mjs",11389,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fexplainer\u002Fwriting.mjs",{"path":384,"resourceType":355,"resourceTypeDesc":356,"sizeBytes":385,"sourceHtmlUrl":386},"ldap-seed.ldif",1110,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Fldap-seed.ldif",{"path":388,"resourceType":388,"resourceTypeDesc":389,"sizeBytes":390,"sourceHtmlUrl":391},"LICENSE","许可证",11358,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002FLICENSE",{"path":393,"resourceType":388,"resourceTypeDesc":389,"sizeBytes":394,"sourceHtmlUrl":395},"LICENSE-MIT",1102,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002FLICENSE-MIT",{"path":397,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":398,"sourceHtmlUrl":399},"locales\u002Far.json",33837,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Far.json",{"path":401,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":402,"sourceHtmlUrl":403},"locales\u002Fen.json",27386,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Fen.json",{"path":405,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":406,"sourceHtmlUrl":407},"locales\u002Fes.json",29504,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Fes.json",{"path":409,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":410,"sourceHtmlUrl":411},"locales\u002Fko.json",30852,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Fko.json",{"path":413,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":414,"sourceHtmlUrl":415},"locales\u002Fmanifest.json",293,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Fmanifest.json",{"path":417,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":418,"sourceHtmlUrl":419},"locales\u002FREADME.md",2235,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002FREADME.md",{"path":421,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":422,"sourceHtmlUrl":423},"locales\u002Fzh-CN.json",27080,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Fzh-CN.json",{"path":425,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":426,"sourceHtmlUrl":427},"locales\u002Fzh-TW.json",27147,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Flocales\u002Fzh-TW.json",{"path":429,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":430,"sourceHtmlUrl":431},"migrations\u002Fworkflow-v2.mjs",9204,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fmigrations\u002Fworkflow-v2.mjs",{"path":433,"resourceType":355,"resourceTypeDesc":356,"sizeBytes":434,"sourceHtmlUrl":435},"NOTICE",1340,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002FNOTICE",{"path":437,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":438,"sourceHtmlUrl":439},"package-lock.json",3232,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fpackage-lock.json",{"path":441,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":442,"sourceHtmlUrl":443},"package.json",1485,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fpackage.json",{"path":445,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":446,"sourceHtmlUrl":447},"rbac-demo\u002Fdocker-compose.yml",5264,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fdocker-compose.yml",{"path":449,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":450,"sourceHtmlUrl":451},"rbac-demo\u002Fdown.sh",1211,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fdown.sh",{"path":453,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":454,"sourceHtmlUrl":455},"rbac-demo\u002Fotel-collector-config.yaml",1276,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fotel-collector-config.yaml",{"path":457,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":458,"sourceHtmlUrl":459},"rbac-demo\u002Froles.json",747,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Froles.json",{"path":461,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":462,"sourceHtmlUrl":463},"rbac-demo\u002Fup.sh",4338,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fup.sh",{"path":465,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":466,"sourceHtmlUrl":467},"rbac-demo\u002Fusers.json",1495,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Flocal-boot\u002Frbac-demo\u002Fusers.json",{"path":469,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":470,"sourceHtmlUrl":471},"recipes\u002Fscenarios.mjs",41520,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frecipes\u002Fscenarios.mjs",{"path":473,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":474,"sourceHtmlUrl":475},"references\u002Farchitecture-layout-repair.md",4449,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Farchitecture-layout-repair.md",{"path":477,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":478,"sourceHtmlUrl":479},"references\u002Fauthoring-contract.md",42749,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fauthoring-contract.md",{"path":481,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":482,"sourceHtmlUrl":483},"references\u002Fauthoring-defaults.md",12862,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fauthoring-defaults.md",{"path":485,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":486,"sourceHtmlUrl":487},"references\u002Fbrand-marks.md",5771,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fbrand-marks.md",{"path":489,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":490,"sourceHtmlUrl":491},"references\u002Fdelivery-contract.md",49894,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fdelivery-contract.md",{"path":493,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":494,"sourceHtmlUrl":495},"references\u002Fexplainer-authoring.md",18968,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fexplainer-authoring.md",{"path":497,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":498,"sourceHtmlUrl":499},"references\u002Frepository-authoring.md",8004,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Frepository-authoring.md",{"path":501,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":502,"sourceHtmlUrl":503},"references\u002Fupdate-awareness.md",1957,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fupdate-awareness.md",{"path":505,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":506,"sourceHtmlUrl":507},"references\u002Fviewer-runtime.md",5692,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Freferences\u002Fviewer-runtime.md",{"path":509,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":510,"sourceHtmlUrl":511},"renderers\u002Farchitecture\u002Fgrid.mjs",2071,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Farchitecture\u002Fgrid.mjs",{"path":513,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":514,"sourceHtmlUrl":515},"renderers\u002Farchitecture\u002Flabels.mjs",155,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Farchitecture\u002Flabels.mjs",{"path":517,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":518,"sourceHtmlUrl":519},"renderers\u002Farchitecture\u002Frender-architecture.mjs",58551,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Farchitecture\u002Frender-architecture.mjs",{"path":521,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":522,"sourceHtmlUrl":523},"renderers\u002Farchitecture\u002Frouting.mjs",74482,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Farchitecture\u002Frouting.mjs",{"path":525,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":526,"sourceHtmlUrl":527},"renderers\u002Fclass\u002FREADME.md",6781,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fclass\u002FREADME.md",{"path":529,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":530,"sourceHtmlUrl":531},"renderers\u002Fclass\u002Frender-class.mjs",53567,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fclass\u002Frender-class.mjs",{"path":533,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":534,"sourceHtmlUrl":535},"renderers\u002Fdataflow\u002Fdataflow-compiler.mjs",91209,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fdataflow\u002Fdataflow-compiler.mjs",{"path":537,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":538,"sourceHtmlUrl":539},"renderers\u002Fdataflow\u002Fjoint-label-routing.mjs",10827,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fdataflow\u002Fjoint-label-routing.mjs",{"path":541,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":542,"sourceHtmlUrl":543},"renderers\u002Fdataflow\u002Flabel-capacity.mjs",4454,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fdataflow\u002Flabel-capacity.mjs",{"path":545,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":546,"sourceHtmlUrl":547},"renderers\u002Fdataflow\u002FREADME.md",9193,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fdataflow\u002FREADME.md",{"path":549,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":550,"sourceHtmlUrl":551},"renderers\u002Fdataflow\u002Frender-dataflow.mjs",960,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fdataflow\u002Frender-dataflow.mjs",{"path":553,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":554,"sourceHtmlUrl":555},"renderers\u002Ferd\u002Fgrid.mjs",7038,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ferd\u002Fgrid.mjs",{"path":557,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":558,"sourceHtmlUrl":559},"renderers\u002Ferd\u002FREADME.md",14516,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ferd\u002FREADME.md",{"path":561,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":562,"sourceHtmlUrl":563},"renderers\u002Ferd\u002Frender-erd.mjs",80473,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ferd\u002Frender-erd.mjs",{"path":565,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":566,"sourceHtmlUrl":567},"renderers\u002Fexplainer\u002Frender-explainer.mjs",3292,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fexplainer\u002Frender-explainer.mjs",{"path":569,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":570,"sourceHtmlUrl":571},"renderers\u002Flifecycle\u002FREADME.md",6167,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Flifecycle\u002FREADME.md",{"path":573,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":574,"sourceHtmlUrl":575},"renderers\u002Flifecycle\u002Frender-lifecycle.mjs",61373,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Flifecycle\u002Frender-lifecycle.mjs",{"path":577,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":578,"sourceHtmlUrl":579},"renderers\u002Fsequence\u002FREADME.md",8667,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fsequence\u002FREADME.md",{"path":581,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":582,"sourceHtmlUrl":583},"renderers\u002Fsequence\u002Frender-sequence.mjs",57144,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fsequence\u002Frender-sequence.mjs",{"path":585,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":586,"sourceHtmlUrl":587},"renderers\u002Fshared\u002Fatomic-output.mjs",70372,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fatomic-output.mjs",{"path":589,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":590,"sourceHtmlUrl":591},"renderers\u002Fshared\u002Fautomatic-labels.mjs",14771,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fautomatic-labels.mjs",{"path":593,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":594,"sourceHtmlUrl":595},"renderers\u002Fshared\u002Fbrand-marks.mjs",28938,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fbrand-marks.mjs",{"path":597,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":598,"sourceHtmlUrl":599},"renderers\u002Fshared\u002Fcli.mjs",19047,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fcli.mjs",{"path":601,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":602,"sourceHtmlUrl":603},"renderers\u002Fshared\u002Fdesktop-readability.mjs",6929,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fdesktop-readability.mjs",{"path":605,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":606,"sourceHtmlUrl":607},"renderers\u002Fshared\u002Fdiagnostics.mjs",8272,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fdiagnostics.mjs",{"path":609,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":610,"sourceHtmlUrl":611},"renderers\u002Fshared\u002Fengineering-profiles.mjs",6936,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fengineering-profiles.mjs",{"path":613,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":614,"sourceHtmlUrl":615},"renderers\u002Fshared\u002Fgenerated-brand-marks.mjs",163612,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fgenerated-brand-marks.mjs",{"path":617,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":618,"sourceHtmlUrl":619},"renderers\u002Fshared\u002Fgenerated-validators.mjs",1020040,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fgenerated-validators.mjs",{"path":621,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":622,"sourceHtmlUrl":623},"renderers\u002Fshared\u002Fgeometry.mjs",89929,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fgeometry.mjs",{"path":625,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":626,"sourceHtmlUrl":627},"renderers\u002Fshared\u002Fi18n.mjs",13869,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fi18n.mjs",{"path":629,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":630,"sourceHtmlUrl":631},"renderers\u002Fshared\u002Flayout-report.mjs",1587,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Flayout-report.mjs",{"path":633,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":634,"sourceHtmlUrl":635},"renderers\u002Fshared\u002Flegend.mjs",9225,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Flegend.mjs",{"path":637,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":638,"sourceHtmlUrl":639},"renderers\u002Fshared\u002Fnode-card-style.mjs",2470,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fnode-card-style.mjs",{"path":641,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":642,"sourceHtmlUrl":643},"renderers\u002Fshared\u002Foutput-path.mjs",19029,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Foutput-path.mjs",{"path":645,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":646,"sourceHtmlUrl":647},"renderers\u002Fshared\u002Fowned-temp-directory.mjs",3198,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fowned-temp-directory.mjs",{"path":649,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":650,"sourceHtmlUrl":651},"renderers\u002Fshared\u002Fpath-semantics.mjs",32406,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fpath-semantics.mjs",{"path":653,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":654,"sourceHtmlUrl":655},"renderers\u002Fshared\u002Fportable-path.mjs",12543,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fportable-path.mjs",{"path":657,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":658,"sourceHtmlUrl":659},"renderers\u002Fshared\u002Frepository-evidence.mjs",20342,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Frepository-evidence.mjs",{"path":661,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":662,"sourceHtmlUrl":663},"renderers\u002Fshared\u002Frepository-location.mjs",4349,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Frepository-location.mjs",{"path":665,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":666,"sourceHtmlUrl":667},"renderers\u002Fshared\u002Froute-quality.mjs",26944,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Froute-quality.mjs",{"path":669,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":670,"sourceHtmlUrl":671},"renderers\u002Fshared\u002Fsidecar-path.mjs",1269,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fsidecar-path.mjs",{"path":673,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":674,"sourceHtmlUrl":675},"renderers\u002Fshared\u002Fsoftware-notices.mjs",506,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fsoftware-notices.mjs",{"path":677,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":678,"sourceHtmlUrl":679},"renderers\u002Fshared\u002Fspatial-grid.mjs",2440,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fspatial-grid.mjs",{"path":681,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":682,"sourceHtmlUrl":683},"renderers\u002Fshared\u002Fsvg-path-analysis.mjs",5429,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fsvg-path-analysis.mjs",{"path":685,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":686,"sourceHtmlUrl":687},"renderers\u002Fshared\u002Ftext-fit.mjs",5195,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Ftext-fit.mjs",{"path":689,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":690,"sourceHtmlUrl":691},"renderers\u002Fshared\u002Futils.mjs",12972,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Futils.mjs",{"path":693,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":694,"sourceHtmlUrl":695},"renderers\u002Fshared\u002Fvalidator.mjs",3336,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fshared\u002Fvalidator.mjs",{"path":697,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":698,"sourceHtmlUrl":699},"renderers\u002Ftimeline\u002FREADME.md",4087,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ftimeline\u002FREADME.md",{"path":701,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":702,"sourceHtmlUrl":703},"renderers\u002Ftimeline\u002Frender-timeline.mjs",30321,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ftimeline\u002Frender-timeline.mjs",{"path":705,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":706,"sourceHtmlUrl":707},"renderers\u002Ftree\u002FREADME.md",4255,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ftree\u002FREADME.md",{"path":709,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":710,"sourceHtmlUrl":711},"renderers\u002Ftree\u002Frender-tree.mjs",30666,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Ftree\u002Frender-tree.mjs",{"path":713,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":714,"sourceHtmlUrl":715},"renderers\u002Fwaterfall\u002FREADME.md",3501,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fwaterfall\u002FREADME.md",{"path":717,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":718,"sourceHtmlUrl":719},"renderers\u002Fwaterfall\u002Frender-waterfall.mjs",23030,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fwaterfall\u002Frender-waterfall.mjs",{"path":721,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":722,"sourceHtmlUrl":723},"renderers\u002Fworkflow\u002FREADME.md",17670,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fworkflow\u002FREADME.md",{"path":725,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":726,"sourceHtmlUrl":727},"renderers\u002Fworkflow\u002Frender-workflow.mjs",1654,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fworkflow\u002Frender-workflow.mjs",{"path":729,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":730,"sourceHtmlUrl":731},"renderers\u002Fworkflow\u002Fworkflow-compiler.mjs",250196,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fworkflow\u002Fworkflow-compiler.mjs",{"path":733,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":734,"sourceHtmlUrl":735},"renderers\u002Fworkflow\u002Fworkflow-migration-geometry.mjs",6331,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fworkflow\u002Fworkflow-migration-geometry.mjs",{"path":737,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":738,"sourceHtmlUrl":739},"renderers\u002Fworkflow\u002Fworkflow-placement-repair.mjs",4762,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Frenderers\u002Fworkflow\u002Fworkflow-placement-repair.mjs",{"path":741,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":742,"sourceHtmlUrl":743},"schemas\u002Farchitecture.schema.json",6024,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Farchitecture.schema.json",{"path":745,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":746,"sourceHtmlUrl":747},"schemas\u002Fclass.schema.json",8120,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fclass.schema.json",{"path":749,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":750,"sourceHtmlUrl":751},"schemas\u002Fcommon.schema.json",5785,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fcommon.schema.json",{"path":753,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":754,"sourceHtmlUrl":755},"schemas\u002Fdataflow.schema.json",6320,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fdataflow.schema.json",{"path":757,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":758,"sourceHtmlUrl":759},"schemas\u002Ferd.schema.json",9329,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Ferd.schema.json",{"path":761,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":762,"sourceHtmlUrl":763},"schemas\u002Fexplainer.schema.json",19246,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fexplainer.schema.json",{"path":765,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":766,"sourceHtmlUrl":767},"schemas\u002Flifecycle.schema.json",5342,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Flifecycle.schema.json",{"path":769,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":770,"sourceHtmlUrl":771},"schemas\u002FREADME.md",15049,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002FREADME.md",{"path":773,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":774,"sourceHtmlUrl":775},"schemas\u002Fsequence.schema.json",6178,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fsequence.schema.json",{"path":777,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":778,"sourceHtmlUrl":779},"schemas\u002Ftimeline.schema.json",3951,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Ftimeline.schema.json",{"path":781,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":782,"sourceHtmlUrl":783},"schemas\u002Ftree.schema.json",3172,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Ftree.schema.json",{"path":785,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":786,"sourceHtmlUrl":787},"schemas\u002Fwaterfall.schema.json",3526,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fwaterfall.schema.json",{"path":789,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":790,"sourceHtmlUrl":791},"schemas\u002Fworkflow.schema.json",10165,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fschemas\u002Fworkflow.schema.json",{"path":793,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":794,"sourceHtmlUrl":795},"scripts\u002Fcheck-render-output.mjs",68465,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Fcheck-render-output.mjs",{"path":797,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":798,"sourceHtmlUrl":799},"scripts\u002Fcheck-update.mjs",59332,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Fcheck-update.mjs",{"path":801,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":802,"sourceHtmlUrl":803},"scripts\u002Fdelivery-update-child.mjs",1296,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Fdelivery-update-child.mjs",{"path":805,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":806,"sourceHtmlUrl":807},"scripts\u002Fgenerate-brand-marks.mjs",5136,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Fgenerate-brand-marks.mjs",{"path":809,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":810,"sourceHtmlUrl":811},"scripts\u002Fgenerate-validators.mjs",4172,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Fgenerate-validators.mjs",{"path":813,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":814,"sourceHtmlUrl":815},"scripts\u002Frender-examples.mjs",2024,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Frender-examples.mjs",{"path":817,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":818,"sourceHtmlUrl":819},"scripts\u002Fupdate-contract.mjs",6826,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fscripts\u002Fupdate-contract.mjs",{"path":821,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":822,"sourceHtmlUrl":823},"skill-release.json",260,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002Fskill-release.json",{"path":825,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":826,"sourceHtmlUrl":827},"THIRD_PARTY_NOTICES.md",5669,"https:\u002F\u002Fgithub.com\u002Faliyome\u002Fenv\u002Fblob\u002Fmaster\u002F.rulesync\u002Fskills\u002F.curated\u002Farchify\u002FTHIRD_PARTY_NOTICES.md",[829,855],{"skillNo":830,"name":831,"nameZh":6,"description":832,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":833,"categories":834,"keywords":840,"publishedAt":28},"01M6ACVB23NM9FCW05HZPNA2V1","pull-request","Open a pull request for the current Horizon UI branch the right way — run the full preflight gate first (changelog + docs updated, type-check + build \"compiling passed\", new UI strings translated across all 8 locales, license headers, lint + unit tests, live-OAP validation), commit with NO AI trailers, push, and open the PR against apache\u002Fskywalking-horizon-ui. After it merges, return to main, fast-forward to latest, and delete the merged local branch.","https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fpull-request\u002FSKILL.md",[835],{"categoryNo":836,"categoryName":837,"taxonomyType":838,"taxonomyTypeDesc":839},"01JBSEEDCAT000000000000007","代码审查","SCENARIO","使用场景",[841,842,27,843,844,9,845,846,847,848,849,850,851,852,853,854],"pull request","pull","license","skywalking","push","changelog","validation","lint","run","delete","pr","commit","unit tests","docs",{"skillNo":856,"name":857,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":858,"categories":859,"keywords":868,"publishedAt":28},"01M6ACV56VGHYB8QWD8KMZTJZ9","build-dashboard","https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-horizon-ui\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fbuild-dashboard\u002FSKILL.md",[860,863],{"categoryNo":861,"categoryName":862,"taxonomyType":838,"taxonomyTypeDesc":839},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":864,"categoryName":865,"taxonomyType":866,"taxonomyTypeDesc":867},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[869,870],"build dashboard","dashboard"]