Skip to main content

add-a-feature

Add a new feature, put work behind a feature flag, roll something out (per organization, for everyone, cloud or self-hosted), revert or kill a feature, or make a big change to existing behavior such as a new engine. Use BEFORE writing the feature code, and when finishing or removing a rollout.

소스 정보

저장소
different-ai/openwork
최근 소스 활동
2026년 10월 8일 22:57
감지된 SKILL.md 언어
영어
스타
24,131
포크
2,444

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
add-a-feature
description
Add a new feature, put work behind a feature flag, roll something out (per organization, for everyone, cloud or self-hosted), revert or kill a feature, or make a big change to existing behavior such as a new engine. Use BEFORE writing the feature code, and when finishing or removing a rollout.
# Skill: Add a feature Every new user-visible feature, and every change existing users would notice, is a **feature** in the registry, declared **before any feature code**, off. Nothing big ships ungated. Registry: `packages/features/src/registry.ts` (package `@openwork/features`). That file is the only one you edit to declare a feature. The rules live in `resolve.ts` and are tested in `resolve.test.ts` (`pnpm --filter @openwork/features test`). ## The model: one rollout, several dimensions A feature is rolled out, and reverted, along these dimensions, resolved in this order by one function (`resolveFeature`) everywhere it is checked: 1. **Deployments**: products it exists on (`cloud`, `self_hosted`). Fixed in code. 2. **Kill switch**: off everywhere at once, outranking everything below. This is the revert; no deploy. 3. **Operator lock**: a self-hosted operator forces it on or off for the whole install (Helm `config.features.<key>`). 4. **Organization override**: platform admins turn it on or off for one organization in `/admin`. 5. **Everyone**: on or off for everyone on the deployment, changed in `/admin` without a deploy. Steps 2, 4 and 5 are set per deployment in `/admin` (Features page and each organization's row) or with the admin MCP tools `den_list_features`, `den_set_feature_rollout` and `den_set_org_capability`. ## Does this need a feature? Yes, if any of these is true: - People get a new screen, tab, button, tool, route family, worker, or engine. - Existing users would notice the change (a flow works differently, something moves or disappears). - It should roll out gradually, be revertable, or might not belong on self-hosted installs. No for bug fixes, copy changes, refactors and internal tooling. Not a feature either: something that only keeps older clients working (compat shim with a removal condition), something worked out from what is configured (derive it in code), or a setting that changes *how* something works rather than *whether* people get it (put it in `env.ts` / Helm `config.<area>`). ## 1. Declare it, off ```ts newThing: { label: "New thing", description: "What a person gets, in words they see in the product.", since: "2026-10", deployments: ["cloud", "self_hosted"], default: false, }, ``` - **Key**: lowerCamelCase, no consecutive capitals. Permanent: also the Helm key, `DEN_FEATURE_NEW_THING`, the API field and stored rows. - **Deployments**: leave one out on purpose (e.g. `["cloud"]` for a cloud-only feature). - **default**: false for new work. A fresh deployment, and a client that cannot reach Den, uses it, so never ship half-done work as `true`. - **permanent: true** only when the switch itself is part of the product (e.g. turning Connect off for one organization). Rollouts are temporary. Then run `pnpm features:sync`. It regenerates the Helm files **and the Den API contract/SDK** (feature keys are part of API schemas). It prepares a disposable local database and removes it afterwards; MySQL must be running (`pnpm dev:den:mysql`). Commit the Helm files, `packages/docs/openapi.json`, and `packages/sdk/src/gen/**` together. Do not stop after Helm generation if the contract step fails. ## 2. Make it safe to turn off at any moment Before shipping, answer: **what happens when the kill switch is used?** In-flight work, stored data, and what the person sees must survive a revert. For example, a new engine switches only when nothing is running, falls back on failure, and keeps history readable after a revert. ## 3. Gate the code Only through the registry. Never read organization metadata or an environment variable to decide whether a feature is on. - den-api, one check: `await organizationFeatureEnabled(orgId, "newThing", { userId })` - den-api, several checks: `const features = await getOrganizationFeatures(orgId, { userId })` - den-api route guard: `requireFeature("newThing")` after `orgMemberRoute()`; answers 404 `feature_disabled` - Inside a transaction that must stay consistent: pass `{ database: tx, lock: "share" }` - Den web: `orgFeatureEnabled(orgContext, "newThing")` (from `app/(den)/_lib/den-org.ts`), backed by `GET /v1/org` `features` - People without an organization (signed-out desktop): read `GET /v1/features`; a missing key means off Gated UI follows DESIGN.md P4: show a locked entry point with a plain reason rather than silently removing it, when the person could act on it. ## 4. Roll it out 1. Turn it on for our own organization (override in `/admin`). 2. Turn it on for more organizations, one override at a time, checking errors as you go. 3. Turn it on for everyone in `/admin` › Features. Organizations can still be turned off one by one. 4. Anything wrong: **Turn off everywhere** (kill switch). Fix, restore, continue. 5. Once it is on everywhere: set `default: true`, then delete the entry and every check. `pnpm features:check` asks for a decision six months after `since` unless the entry is `permanent`. Evals turn features on per organization through the admin API: `enableOrganizationCapabilities(seed, admin, { newThing: true })` in `evals/worlds/dashboards.ts`. ## Never - Add a `DEN_*_ENABLED` env var for a product surface (CI rejects new ones). - Read or write `organization.metadata.capabilities` (CI rejects it). - Hand-write an `/admin` control, a `/v1/org` field, or a Helm line for a feature. - Ship something on self-hosted by accident: choose `deployments` on purpose. ## In the PR Name the feature and its deployments under "How is this implemented?", e.g. "Behind `newThing` (cloud and self-hosted, off), safe to kill: falls back to the old flow." Run `pnpm features:check` before pushing.
GitHub에서 보기