Agent Skills › different-ai/openwork › add-a-feature

add-a-feature

GitHub

管理功能上线流程,包括在代码前声明功能、配置多阶段灰度发布及回滚开关。适用于需逐步 rollout、可逆或涉及不同部署环境的新增用户可见特性。

.opencode/skills/add-a-feature/SKILL.md different-ai/openwork

Trigger Scenarios

添加新的用户可见功能 配置功能灰度发布策略 执行功能回滚或关闭

Install

npx skills add different-ai/openwork --skill add-a-feature -g -y
More Options

Non-standard path

npx skills add https://github.com/different-ai/openwork/tree/dev/.opencode/skills/add-a-feature -g -y

Use without installing

npx skills use different-ai/openwork@add-a-feature

指定 Agent (Claude Code)

npx skills add different-ai/openwork --skill add-a-feature -a claude-code -g -y

安装 repo 全部 skill

npx skills add different-ai/openwork --all -g -y

预览 repo 内 skill

npx skills add different-ai/openwork --list

SKILL.md

Frontmatter
{
    "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

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.

Version History

  • b73f6c6 Current 2026-10-19 21:56

Same Skill Collection

.opencode/skills/agent-first-screenshots/SKILL.md
.opencode/skills/browser-automation/SKILL.md
.opencode/skills/build-a-witness/SKILL.md
.opencode/skills/cloud-dashboard-walkthrough/SKILL.md
.opencode/skills/create-plugin/SKILL.md
.opencode/skills/daytona-chrome-cdp/SKILL.md
.opencode/skills/daytona-cloud-instance/SKILL.md
.opencode/skills/daytona-cloud-server/SKILL.md
.opencode/skills/daytona-dev/SKILL.md
.opencode/skills/daytona-electron-den/SKILL.md
.opencode/skills/daytona-electron-test/SKILL.md
.opencode/skills/daytona-flow-validator/SKILL.md
.opencode/skills/daytona-recording-artifacts/SKILL.md
.opencode/skills/daytona-secrets-volume/SKILL.md
.opencode/skills/daytona-seeded-cloud-demo/SKILL.md
.opencode/skills/daytona-windows-cert/SKILL.md
.opencode/skills/daytona/SKILL.md
.opencode/skills/diagnose-a-red-run/SKILL.md
.opencode/skills/drive-desktop-cdp/SKILL.md
.opencode/skills/fake-model-faults/SKILL.md
.opencode/skills/fix-design-notes/SKILL.md
.opencode/skills/fraimz/SKILL.md
.opencode/skills/get-env-var/SKILL.md
.opencode/skills/hunt-a-prod-error/SKILL.md
.opencode/skills/measure-chat-flicker/SKILL.md
.opencode/skills/open-a-pr/SKILL.md
.opencode/skills/openwork-models/SKILL.md
.opencode/skills/preview-my-work/SKILL.md
.opencode/skills/product-tutorial-pipeline/SKILL.md
.opencode/skills/prove-a-pr/SKILL.md
.opencode/skills/publish-evidence/SKILL.md
.opencode/skills/record-a-demo/SKILL.md
.opencode/skills/release/SKILL.md
.opencode/skills/reproduce-chat-states/SKILL.md
.opencode/skills/review-a-contributor-pr/SKILL.md
.opencode/skills/run-evals/SKILL.md
.opencode/skills/run-tests/SKILL.md
.opencode/skills/shadcn/SKILL.md
.opencode/skills/upload-photo/SKILL.md
.opencode/skills/validate-a-release/SKILL.md
.opencode/skills/verify-openwork/SKILL.md
.opencode/skills/write-a-spec/SKILL.md
.warden/skills/confidentiality-review/SKILL.md
.warden/skills/contributor-screen/SKILL.md
.warden/skills/design-spec-review/SKILL.md
.warden/skills/desktop-den-sync-review/SKILL.md
.warden/skills/diff-security-review/SKILL.md
.warden/skills/spec-provenance-review/SKILL.md
integrations/agent-plugins/openwork-connect/skills/openwork-connect/SKILL.md

Metadata

Files
0
Version
b73f6c6
Hash
06e8b0a2
Indexed
2026-10-19 21:56

홈 - 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-24 21:56
浙ICP备14020137号-1