/**
 * Auto-generated by scripts/sop-definitions.mjs.
 * Do not edit by hand. Run: pnpm gen:sop-definitions
 */

export const SOP_DEFINITION_IDS = ['development'] as const;
export type SopDefinitionId = (typeof SOP_DEFINITION_IDS)[number];

export const DEVELOPMENT_SOP_STAGE_IDS = ['kickoff', 'impl', 'quality_gate', 'review', 'merge', 'completion'] as const;
export type DevelopmentSopStageId = (typeof DEVELOPMENT_SOP_STAGE_IDS)[number];
export const DEVELOPMENT_SOP_DEFINITION = {
  id: 'development',
  domain: 'engineering',
  label: 'Development SOP',
  description: 'Cat Cafe coding feature lifecycle. This is the runtime SOP definition used by WorkflowSop.',
  stages: [
    {
      id: 'kickoff',
      label: '立项',
      suggestedSkill: 'feat-lifecycle',
      hardRules: [
        {
          id: 'kickoff-ac-checklist',
          kind: 'hard_rule',
          text: 'Feature spec 必须有 AC + 需求点 checklist',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'feat-lifecycle' },
          predicate: {
            type: 'manual_only',
            reason: 'Feature spec completeness is reviewed from docs and CVO context; no stable machine artifact yet.',
          },
        },
      ],
      pitfalls: [
        {
          id: 'kickoff-no-unconfirmed-implementation',
          kind: 'pitfall',
          text: '没有铲屎官确认就直接开始实现',
          severity: 'warn',
          owner: { type: 'stage_suggested_skill', skill: 'feat-lifecycle' },
          predicate: {
            type: 'manual_only',
            reason: 'CVO confirmation is conversational intent, not yet represented as a structured event.',
          },
        },
      ],
    },
    {
      id: 'impl',
      label: '实现',
      suggestedSkill: 'writing-plans',
      hardRules: [
        {
          id: 'impl-main-sync-before-worktree',
          kind: 'hard_rule',
          text: 'worktree 开之前必须 main 双向同步 (ahead=0 behind=0)',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'writing-plans' },
          predicate: {
            type: 'git_state_predicate',
            repository: 'cat-cafe',
            branch: 'main',
            checks: ['ahead_zero', 'behind_zero'],
            beforeCommand: 'git worktree add',
          },
        },
        {
          id: 'impl-redis-6398-only',
          kind: 'hard_rule',
          text: 'Redis 只用 6398，禁碰 6399',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'writing-plans' },
          predicate: { type: 'env_check', key: 'REDIS_URL', mustInclude: ':6398', mustNotInclude: ':6399' },
        },
      ],
      pitfalls: [
        {
          id: 'impl-design-gate-before-code',
          kind: 'pitfall',
          text: '跳过 Design Gate 直接写代码',
          severity: 'warn',
          owner: { type: 'stage_suggested_skill', skill: 'writing-plans' },
          predicate: {
            type: 'manual_only',
            reason: 'Design Gate evidence is feature-specific and not yet represented by a structured artifact.',
          },
        },
        {
          id: 'impl-post-compact-recall-loss',
          kind: 'pitfall',
          text: '压缩后忘了当前在做什么',
          severity: 'warn',
          owner: { type: 'stage_suggested_skill', skill: 'writing-plans' },
          predicate: {
            type: 'manual_only',
            reason: 'Current runtime has no stable post-compact recall-failure telemetry.',
            futureCandidate: 'trace_pattern_post_compact_recall',
          },
        },
      ],
    },
    {
      id: 'quality_gate',
      label: '自检',
      suggestedSkill: 'quality-gate',
      hardRules: [
        {
          id: 'quality-gate-vision-coverage',
          kind: 'hard_rule',
          text: '自检报告必须包含愿景覆盖度',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'quality-gate' },
          predicate: {
            type: 'manual_only',
            reason:
              'Vision coverage has no machine-checkable report artifact yet; upgrade when quality-gate emits structured evidence.',
            futureCandidate: 'quality_gate_report_artifact',
          },
        },
      ],
      pitfalls: [
        {
          id: 'quality-gate-full-test-evidence',
          kind: 'pitfall',
          text: '声称完成但没跑全量测试',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'quality-gate' },
          predicate: { type: 'command_pattern', mustMatch: 'pnpm gate|pnpm test|pnpm --filter .* test|node --test' },
        },
      ],
    },
    {
      id: 'review',
      label: 'Review',
      suggestedSkill: 'request-review',
      hardRules: [
        {
          id: 'review-no-self-review',
          kind: 'hard_rule',
          text: '同一个体不能 review 自己的代码',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'request-review' },
          predicate: { type: 'handle_check', constraint: 'reviewer_not_author' },
        },
        {
          id: 'review-original-requirements',
          kind: 'hard_rule',
          text: 'Review 请求必须附原始需求摘录',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'request-review' },
          predicate: {
            type: 'manual_only',
            reason: 'Review packet content is free-form markdown; no structured requirement-excerpt field yet.',
            futureCandidate: 'review_packet_schema',
          },
        },
      ],
      pitfalls: [
        {
          id: 'review-retrigger-after-p1',
          kind: 'pitfall',
          text: '收到 P1 修完后没 re-trigger review',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'request-review' },
          predicate: {
            type: 'command_sequence',
            absent: ['@codex review'],
            mustInclude: ['git push', 'gh pr comment'],
          },
        },
      ],
    },
    {
      id: 'merge',
      label: '合入',
      suggestedSkill: 'merge-gate',
      hardRules: [
        {
          id: 'merge-github-squash-only',
          kind: 'hard_rule',
          text: '必须用 gh pr merge --squash（禁止本地 squash）',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'merge-gate' },
          predicate: {
            type: 'command_pattern',
            mustMatch: 'gh pr merge .*--squash',
            mustNotMatch: 'git merge --squash|git reset --soft',
          },
        },
        {
          id: 'merge-cloud-review-sha-dedup',
          kind: 'hard_rule',
          text: '云端 review 同一 SHA 不重复触发',
          severity: 'warn',
          owner: { type: 'stage_suggested_skill', skill: 'merge-gate' },
          predicate: { type: 'sha_dedup', scope: 'cloud_review' },
        },
      ],
      pitfalls: [
        {
          id: 'merge-local-squash-close',
          kind: 'pitfall',
          text: '本地 squash + push + gh pr close（PR 显示 closed 不是 merged）',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'merge-gate' },
          predicate: { type: 'command_sequence', absent: ['gh pr merge'], antiPattern: ['git push', 'gh pr close'] },
        },
        {
          id: 'merge-runtime-update-after-merge',
          kind: 'pitfall',
          text: '合入后擅自更新 runtime',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'merge-gate' },
          predicate: {
            type: 'command_sequence',
            antiPattern: ['git pull', 'pnpm start|runtime:start|restart'],
            cwdContains: 'cat-cafe-runtime',
          },
        },
      ],
    },
    {
      id: 'completion',
      label: '完成',
      suggestedSkill: 'feat-lifecycle',
      hardRules: [
        {
          id: 'completion-vision-guardian',
          kind: 'hard_rule',
          text: 'feat close 前必须跨猫愿景守护',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'feat-lifecycle' },
          predicate: {
            type: 'manual_only',
            reason: 'Guardian identity and signoff are still conversational/thread-state artifacts.',
            futureCandidate: 'guardian_signoff_event',
          },
        },
        {
          id: 'completion-pr-merged-feature-check',
          kind: 'hard_rule',
          text: 'PR merged + check:features 通过',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'feat-lifecycle' },
          predicate: { type: 'command_sequence', mustInclude: ['gh pr view', 'pnpm check:features'] },
        },
      ],
      pitfalls: [
        {
          id: 'completion-missing-guardian-handoff',
          kind: 'pitfall',
          text: '没有 @ 其他猫做愿景守护就直接 close',
          severity: 'blocker',
          owner: { type: 'stage_suggested_skill', skill: 'feat-lifecycle' },
          predicate: { type: 'handle_check', constraint: 'guardian_handoff_present' },
        },
      ],
    },
  ],
  sourcePath: 'sop-definitions/development.yaml',
} as const;

export const SOP_DEFINITIONS = {
  development: DEVELOPMENT_SOP_DEFINITION,
} as const;

export type SopDefinition = (typeof SOP_DEFINITIONS)[SopDefinitionId];
export const DEFAULT_SOP_DEFINITION_ID = SOP_DEFINITION_IDS[0];
export type RuntimeSopStageId = DevelopmentSopStageId;

export type ResolvedWorkflowSopSkill = {
  readonly source: 'definition' | 'override';
  readonly skill: string;
};

export function isSopDefinitionId(value: string): value is SopDefinitionId {
  return (SOP_DEFINITION_IDS as readonly string[]).includes(value);
}

export function normalizeSopDefinitionId(value: string | null | undefined): SopDefinitionId {
  return value && isSopDefinitionId(value) ? value : DEFAULT_SOP_DEFINITION_ID;
}

export function getSopDefinition(id: string | null | undefined): SopDefinition {
  return SOP_DEFINITIONS[normalizeSopDefinitionId(id)];
}

export function resolveWorkflowSopSkill(sop: {
  readonly sopDefinitionId?: string | null;
  readonly stage: RuntimeSopStageId;
  readonly nextSkill?: string | null;
}): ResolvedWorkflowSopSkill {
  const definition = getSopDefinition(sop.sopDefinitionId);
  const stage = definition.stages.find((entry) => entry.id === sop.stage);
  if (!stage) {
    throw new Error(`Unknown SOP stage "${sop.stage}" for definition "${definition.id}"`);
  }
  if (sop.nextSkill) {
    return { source: 'override', skill: sop.nextSkill };
  }
  return { source: 'definition', skill: stage.suggestedSkill };
}
