본문으로 건너뛰기
cccskills
무료GitHub에 공개

generated-files

Never hand-edit or hand-copy generated content. Use when touching permissions.rs, error.rs, AppError/SearchError variants, runtimes/catalog.fallback.json, any `#[derive(specta::Type)]` struct, any file with an AUTO-GENERATED banner (kinds.ts, gatedPermissions.ts, knownRuntimes.ts, bindings.ts, emoji data), or whenever you are about to write a TypeScript list/type that mirrors a Rust source.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

Xoshbin/asyar스타 946(GitHub 946 + cccskills 0)

실행 점수 미검증

설치 방법 보기

포함된 파일(1)

  • SKILL.md13.3 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

generated-files

Principle: every list or type that exists on both the Rust side and the TypeScript side has exactly one hand-written source. The other copies are produced by a generator. If you type the second copy by hand, it will drift — and drift here has already shipped real bugs (a permission gate that allowed everything, a publish command that rejected a valid manifest).

The two rules

  1. Never edit a generated file. Edit its Rust/JSON source, then run the generator.
  2. Never create a new hand-synced mirror. If you need Rust data in TS, write a generator — do not paste the list and add a "keep in sync" comment.

Rule 1 — the registry

Files below are outputs. Editing them directly is always wrong; your edit is erased on the next regen and CI fails on the diff.

        SOURCE (hand-written)                 GENERATOR                       OUTPUT (never edit)
  ┌──────────────────────────────┐   ┌───────────────────────────┐   ┌────────────────────────────────┐
  │ src-tauri/src/permissions.rs │──▶│ generate-permission-      │──▶│ src/services/extension/        │
  │   get_required_permission    │   │   catalog.mjs             │  ├▶│   gatedPermissions.ts          │
  └──────────────────────────────┘   │  (writes BOTH copies)     │  │ │ asyar-sdk/cli/lib/             │
                                     └───────────────────────────┘  └▶│   gatedPermissions.ts          │
  ┌──────────────────────────────┐   ┌───────────────────────────┐   ├────────────────────────────────┤
  │ src-tauri/src/error.rs       │──▶│ generate-diagnostic-      │──▶│ src/services/diagnostics/      │
  │ src-tauri/src/search_engine/ │   │   kinds.mjs               │   │   kinds.ts                     │
  │   mod.rs   (error variants)  │   └───────────────────────────┘   ├────────────────────────────────┤
  ├──────────────────────────────┤   ┌───────────────────────────┐   │                                │
  │ src-tauri/src/runtimes/      │──▶│ generate-known-           │──▶│ asyar-sdk/cli/lib/             │
  │   catalog.fallback.json      │   │   runtimes.mjs (in sdk)   │   │   knownRuntimes.ts             │
  ├──────────────────────────────┤   ├───────────────────────────┤   ├────────────────────────────────┤
  │ any #[derive(specta::Type)]  │──▶│ cargo test export_bindings│──▶│ src/bindings.ts   (+ the 3     │
  │ registered in models.rs::    │   │   -- --ignored            │   │   re-export shims under        │
  │   export_bindings            │   │                           │   │   services/search/types/)      │
  ├──────────────────────────────┤   ├───────────────────────────┤   ├────────────────────────────────┤
  │ upstream emoji dataset       │──▶│ extensions/emoji/scripts/ │──▶│ extensions/emoji/src/data/     │
  │                              │   │   generate-data.mjs       │   │   emojis.ts                    │
  └──────────────────────────────┘   └───────────────────────────┘   └────────────────────────────────┘

Concrete commands:

You changedRun (from this directory)
permissions.rs::get_required_permissionpnpm gen:permission-catalog — in asyar-launcher/
AppError / SearchError variantspnpm gen:diagnostic-kinds — in asyar-launcher/
runtimes/catalog.fallback.jsonnpm run gen:known-runtimes — in asyar-sdk/
any of the above (blanket)pnpm gen:all — in that package
a specta::Type struct, or the export listcargo test export_bindings -- --ignored — in src-tauri/
emoji datasetpnpm --filter org.asyar.emoji run gen:data — anywhere

Note the launcher's package name is asyar, not asyar-launcher — so a --filter asyar-launcher will not resolve. cd into the package instead.

You usually don't need to run the first four by hand. pretest, pretest:run, and prebuild all chain gen:all in both packages, so pnpm test self-heals them. bindings.ts is the exception — it needs a full cargo compile, so it is deliberately not in any pretest hook. Changing a specta type means you regenerate it yourself or CI fails.

How to recognise a generated file before you edit it

Line 1 says so. Check it:

// AUTO-GENERATED by scripts/generate-permission-catalog.mjs — do not edit.
// This file has been generated by Specta. Do not edit this file manually.

They are also all listed in .prettierignore — reformatting them just fights the generator's own output style, and diagnostics.rs's kinds_contract test byte-matches kinds.ts's exact "kind" quoting.

The safety nets that will catch you

  • .github/workflows/test-and-lint.yml → "Verify generated Rust-derived files are up to date": the test step already ran gen:all, so a git diff --exit-code on the four generated TS files fails the build if the committed copy was stale.
  • A second step regenerates bindings.ts and diffs it the same way.
  • src-tauri/src/diagnostics.rs::kinds_contract asserts every Rust kind is present in kinds.ts, with the error message telling you which script to run.
  • asyar-launcher/scripts/permission-coverage.test.mjs (picked up by vitest via the scripts/**/*.test.mjs glob) asserts every SDK .invoke() call type is classified gated-or-public in the Rust gate.

A red CI on any of these means "you edited a source and skipped the generator," not "the generator is broken."


Rule 2 — don't hand-write a new mirror

The failure shape to watch for, in your own output:

// ❌ Kept in sync by hand with src-tauri/src/permissions.rs
const GATED = ['clipboard:read', 'network' /* ... */];

That comment is the bug. A comment cannot keep anything in sync. Every instance of this pattern found in this repo had already drifted by the time it was found:

  • permissionCatalog.test.ts's 39-item array was missing feedback:announce, so its "covers every permission" test had a silent hole.
  • manifest.test.ts carried a second, 7-item permission mirror in a different package.
  • VALID_RUNTIMES was hand-typed against known_names().
  • screen:pick-color reached the Rust gate and the JS catalog but not the CLI validator → asyar publish rejected a permission the launcher enforced.

If you are about to write a TS constant whose values come from a Rust file: stop and write a generator instead.

Recipe for a new generated file

Copy asyar-launcher/scripts/generate-permission-catalog.mjs — it is the reference implementation, including the two-output case.

  1. Parse the real source. Read the Rust/JSON file and regex the values out, anchored to a specific function or block (that generator anchors on fn get_required_permission(...) { ... } and throws if the anchor is gone — so a rename fails loudly instead of emitting an empty list).
  2. Dedupe and sort, then JSON.stringify(sorted, null, 2) for the literal.
  3. Write a banner naming the generator, the regen command, and the source. Say what the list is and what it is not — the existing banners spell out that gated ≠ manifest-declarable, which stops the next reader conflating them.
  4. One generator writes every copy. Two consumers that can't share an import (launcher app vs. separately-published SDK CLI) get two targets entries in one script — never two scripts.
  5. Wire it up: add gen:<thing> to that package's package.json, chain it into gen:all (which pretest/pretest:run/prebuild already run).
  6. Add the output to .prettierignore.
  7. Add the output to the CI git diff --exit-code list in .github/workflows/test-and-lint.yml.
  8. Prove it, don't assume it: delete the output and confirm pnpm test:run recreates it byte-identical; corrupt it by hand and confirm git diff --exit-code returns non-zero; run the generator twice and confirm zero drift (idempotent).

A generator without steps 5–7 is a convenience script, not a fix — the staleness gap stays open.


Deliberate exceptions — still hand-maintained

Do not "fix" these by generating them. They are broader or different-purpose lists, not mirrors:

FileWhy it stays hand-written
asyar-sdk/cli/lib/manifest.ts VALID_PERMISSIONSDeliberately broader than the Rust gate — includes declarative-only permissions (store:read, tools:register, runs:track) that get_required_permission never sees. No single Rust source exists.
asyar-launcher/src/services/extension/permissionCatalog.tsHuman-written display copy (title + description) for the consent dialog. Prose, not data.
docs/reference/permissions.md, docs/reference/sdk/README.mdHand-written developer docs that mirror the lists in prose. Known to drift; grep them when adding a permission.

Adding a new permission — the full checklist

One new <namespace>:<action> string still touches five surfaces. Only the generated one is automatic:

1. src-tauri/src/permissions.rs        ← THE source. Enforcement lives here.
2. run gen:permission-catalog          ← writes both gatedPermissions.ts copies
3. asyar-sdk/cli/lib/manifest.ts       ← VALID_PERMISSIONS, by hand
                                          (then `npm run build:cli` — the linked
                                           `asyar` binary runs dist/, not src/)
4. permissionCatalog.ts                ← title + description, by hand
5. docs/reference/permissions.md       ← the table, by hand

Enforcement is Rust only — permissions.rs is the single gate. Steps 3–5 are catalog, consent copy, and docs; none of them enforce anything. The gate fails closed on any call type that get_required_permission and is_public_call both miss.


Red flags — you are violating this skill

  • Editing a file whose first line says AUTO-GENERATED or generated by Specta.
  • Writing // keep in sync with above a TS array.
  • Running prettier --write on a file listed in .prettierignore.
  • Adding a #[derive(specta::Type)] struct and hand-writing the matching TS type instead of .register()-ing it in export_bindings and regenerating. (This exact miss made commands.ts hand-roll a parallel SystemActionId union while the real type sat unregistered.)
  • Changing permissions.rs / error.rs / catalog.fallback.json and calling the task done without running a generator or a test.
  • Reporting a generated-file CI diff as "unrelated" or "pre-existing."

If you catch yourself doing any of these: STOP. Find the source, edit that, regenerate.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Use before planning or implementing ANY feature, bug fix, refactor, or API change that touches Asyar's architecture — extension system, service layer, IPC contracts, Tauri commands, manifest contributions, or cross-layer data flow. Triggers on new features, new extension APIs, new services, bug fixes involving multiple layers, refactors of infrastructure code, adding new contribution points, and any work that could affect how built-in features or third-party extensions interact with the platform. Also triggers on any task where you need to decide which architectural layer owns the logic, whether Tier 2 extensions can use a capability, or whether a change requires a manifest/permission update. Does NOT trigger for pure CSS/styling fixes (use design-language), isolated unit tests, documentation updates, version bumps, mechanical renames, or answering informational questions about the codebase.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

Xoshbin/asyar9462026년 10월 27일 업데이트

Use when building, modifying, or fixing any frontend UI in the Asyar launcher — new components, new views, layout changes, styling decisions, new built-in features, visual bug fixes, and anything in settings or onboarding. Answers "what do I use here?" for fonts, colour, typography, spacing, motion, components, and layout.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

Xoshbin/asyar9462026년 10월 27일 업데이트

Reference for the Asyar monorepo structure, SDK workspace linking, lockfile discipline, CI workflows, and release flow. Use this skill whenever working on anything related to pnpm workspace setup, the asyar-sdk dependency, lockfile errors, SDK or launcher version bumps, CI configuration, release workflow, or questions about how local dev differs from CI. Also triggers for "how does the workspace work", "how do I update the SDK version", "where do I run pnpm install", or any confusion about the monorepo layout.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

Xoshbin/asyar9462026년 10월 27일 업데이트

Audit IPC message contracts between extensions and the Asyar host. Use when adding a new SDK service, adding a new proxy method, changing a postMessage type string, or reviewing permission gate coverage.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

Xoshbin/asyar9462026년 10월 27일 업데이트

tdd

무료

Use when implementing any new feature or fixing any bug in this project — both Rust (src-tauri) and TypeScript/Svelte 5 (src). Triggers on phrases like "add X", "fix Y", "implement Z", "change how W works".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

Xoshbin/asyar9462026년 10월 27일 업데이트

Xoshbin의 스킬 모두 보기

이 스킬의 문제 신고