> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 发布后清理功能开关

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="在发布后清理功能开关" description="安排一次性的 Devin 会话，在发布稳定后移除功能开关及其对应的死代码。" prompt="Next Friday at 9 AM, remove the feature flag 'enable_new_checkout' from our codebase. Delete the flag definition, keep the enabled code path, remove the disabled path, update tests, and open a PR." category="Automations" features="Schedules" type="schedule" />

<div className="uc-detail-wrapper">
  <Tip>不想手动设置？把此页面的链接粘贴到 Devin 会话中，让它为你完成全部设置。</Tip>

  <Steps>
    <Step title="在发布功能开关时就安排清理任务">
      你刚刚在功能开关 `enable_new_checkout` 背后部署了新的结账流程。它已经在生产环境中开启，但你希望先监控一周，再彻底移除旧代码。与其创建一个你可能会忘记的工单，不如趁现在上下文还清晰，立刻安排一次性的 Devin 会话。

      打开[计划创建页面](https://app.devin.ai/settings/schedules/create?utm_source=docs\&utm_medium=use-case-gallery)，将类型设置为 **One-time**。选择监控窗口之后的日期 (例如，下周五上午 9 点) 。选择一个 **Slack channel**，这样当会话运行并且 PR 准备好时，你的团队会收到通知。然后粘贴你的提示词：

      <PromptBlock type="schedule">
        ```txt Clean up feature flag after release theme={null}
        Remove the feature flag "enable_new_checkout" from the codebase:

        1. Delete the flag definition from src/config/featureFlags.ts
        2. Find every conditional that checks this flag (useFeatureFlag, isEnabled,
           if/else branches) and keep only the enabled path
        3. Delete the old checkout implementation that's now unreachable
        4. Remove or update any tests that mock this flag
        5. Run the test suite and open a PR with a summary of what was removed
        ```
      </PromptBlock>
    </Step>

    <Step title="让提示词尽量详尽">
      功能开关可能藏在意想不到的地方——配置文件、测试夹具、注释、环境变量。你在提示词中提供的上下文越多，清理结果就越干净。请包括：

      * **功能开关的工作方式**——它们在哪里定义、如何被检查 (例如在 React 中通过 `useFeatureFlag('name')`，在后端服务中通过 `isEnabled('name')`)
      * **不要动什么**——功能开关框架本身 vs. 某个特定开关 (例如，“不要修改 `src/lib/featureFlags/` —— 那是框架本身”)
      * **新旧代码分别在哪里**——例如，“旧的结账流程在 `src/pages/checkout/legacy/`，新的流程在 `src/pages/checkout/v2/`”
      * **清理范围**——引用该开关的注释、文档、`.env` 文件以及 CI 配置也都应一并清理

      具备这种细节程度的提示词可以让 Devin 一次性追踪所有引用——无需后续再做补充清扫。
    </Step>

    <Step title="在 PR 提交后进行审查">
      当预定会话触发时，Devin 会遍历整个代码库中所有对该开关的使用，保留启用的代码路径，移除禁用路径和死代码，清理测试，并创建一个 PR。PR 准备好后，你会收到邮件通知。

      一个典型的 PR 看起来像这样：

      ```
      Removed feature flag: enable_new_checkout

      - Deleted flag from src/config/featureFlags.ts (1 file)
      - Removed 12 conditional branches across 7 files
      - Deleted src/pages/checkout/legacy/ (4 files, 380 lines)
      - Updated 3 test files — removed flag mocking, deleted old-path tests
      - All 1,204 tests passing
      ```

      在合并之前，再次确认旧路径中的业务逻辑是否有需要保留的部分——错误处理、埋点事件或边界情况兜底有时会放在“disabled”分支中。
    </Step>
  </Steps>
</div>
