teamix-evo 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -167,30 +167,36 @@ TEAMIX_DEBUG=1 teamix-evo tokens init opentrek
167
167
 
168
168
  ## 命令参考
169
169
 
170
- | 命令 | 说明 |
171
- | --------------------------------------------------- | -------------------------------------------------------------- |
172
- | `teamix-evo tokens init <variant>` | 初始化 tokens |
173
- | `teamix-evo tokens list-variants` | 列出可用 variant |
174
- | `teamix-evo tokens list` | 查看已装机的 variant |
175
- | `teamix-evo tokens update` | 更新已装资源(stub,v0.7 ADR 0019) |
176
- | `teamix-evo tokens uninstall` | 卸载已装 tokens |
177
- | `teamix-evo skills init` | 自举 skills(按 variant + scope 全装 — ADR 0034) |
178
- | `teamix-evo skills add <name...>` | 增量装指定 skill(`<name...>` 必填) |
179
- | `teamix-evo skills list` | 列出所有 skill 的安装状态 |
180
- | `teamix-evo skills update [name...] [--dry-run]` | 升级 skills(双闸 + version 短路 — ADR 0035) |
181
- | `teamix-evo skills sync [name...]` | IDE 镜像(漂移恢复用) |
182
- | `teamix-evo skills doctor` | 检测源/镜像漂移(ADR 0013) |
183
- | `teamix-evo skills uninstall` | 卸载 skills( + 镜像 + lock) |
184
- | `teamix-evo ui init` | 初始化 ui 配置(aliases / iconLibrary / tsx / rsc) |
185
- | `teamix-evo ui add <id...>` | 安装指定 ui 组件源码 |
186
- | `teamix-evo ui list [--installed]` | 列出可用/已安装 ui 组件 |
187
- | `teamix-evo biz-ui list-variants` | 列出 biz-ui 包内提供的业务变体 |
188
- | `teamix-evo biz-ui add <id...> --variant <name>` | 安装变体感知业务组件(`--variant` 必填) |
189
- | `teamix-evo templates list-variants` | 列出 templates 包内提供的页面模板变体 |
190
- | `teamix-evo templates add <id...> --variant <name>` | 安装变体感知页面模板(`--variant` 必填) |
191
- | `teamix-evo lint init [-y]` | 一键安装 ESLint + Stylelint token-discipline 规则集 |
192
- | `teamix-evo logs analyze [...]` | 分析 vibe-logger AI 调用链(`.log/ai/**/*.jsonl`) |
193
- | `teamix-evo logs trace [...]` | 按会话还原 AI 调用链(prompt → PreToolUse → PostToolUse → Stop) |
170
+ | 命令 | 说明 |
171
+ | --------------------------------------------------- | ------------------------------------------------------------------------------- |
172
+ | `teamix-evo init [-y] [--dry-run] [--variant <n>]` | 普通版接入:检测冲突 → wizard → 静默落地(已有 npm 工程入口) |
173
+ | `teamix-evo update [--dry-run] [--cwd <dir>]` | 一键升级已装资源(tokens + skills,ADR 0003 三态 + ADR 0035 短路) |
174
+ | `teamix-evo restore [ts] [--list] [-y]` | 回滚 `.teamix-evo/` 到指定 snapshot(ADR 0019 §2 — 自身可逆) |
175
+ | `teamix-evo switch <new-variant> [--apply] [-y]` | variant 切换:默认 dry-run 展示 file-level diff,--apply 才真写(ADR 0019 §D3) |
176
+ | `teamix-evo tokens init <variant>` | 初始化 tokens |
177
+ | `teamix-evo tokens list-variants` | 列出可用 variant |
178
+ | `teamix-evo tokens list` | 查看已装机的 variant |
179
+ | `teamix-evo tokens update` | 更新已装资源(stub,v0.7 ADR 0019) |
180
+ | `teamix-evo tokens uninstall` | 卸载已装 tokens |
181
+ | `teamix-evo tokens audit` | 审计 tokens 引用(4 类:redundant / kept / migrate / custom,v3↔v4 语义比较) |
182
+ | `teamix-evo skills init` | 自举 skills(按 variant + scope 全装 — ADR 0034) |
183
+ | `teamix-evo skills add <name...>` | 增量装指定 skill(`<name...>` 必填) |
184
+ | `teamix-evo skills list` | 列出所有 skill 的安装状态 |
185
+ | `teamix-evo skills update [name...] [--dry-run]` | 升级 skills(双闸 + version 短路 — ADR 0035) |
186
+ | `teamix-evo skills sync [name...]` | IDE 镜像(漂移恢复用) |
187
+ | `teamix-evo skills doctor` | 检测源/镜像漂移(ADR 0013) |
188
+ | `teamix-evo skills uninstall` | 卸载 skills(源 + 镜像 + lock) |
189
+ | `teamix-evo ui init` | 初始化 ui 配置(aliases / iconLibrary / tsx / rsc) |
190
+ | `teamix-evo ui add <id...>` | 安装指定 ui 组件源码 |
191
+ | `teamix-evo ui list [--installed]` | 列出可用/已安装 ui 组件 |
192
+ | `teamix-evo ui promote-to-biz <id...>` | ui 组件提升为业务组件(8 模式:Coexist/Preset/Wrapper/Compose/Variant/Fork/TokenOnly/ManualReview) |
193
+ | `teamix-evo biz-ui list-variants` | 列出 biz-ui 包内提供的业务变体 |
194
+ | `teamix-evo biz-ui add <id...> --variant <name>` | 安装变体感知业务组件(`--variant` 必填) |
195
+ | `teamix-evo templates list-variants` | 列出 templates 包内提供的页面模板变体 |
196
+ | `teamix-evo templates add <id...> --variant <name>` | 安装变体感知页面模板(`--variant` 必填) |
197
+ | `teamix-evo lint init [-y]` | 一键安装 ESLint + Stylelint token-discipline 规则集 |
198
+ | `teamix-evo logs analyze [...]` | 分析 vibe-logger AI 调用链(`.log/ai/**/*.jsonl`) |
199
+ | `teamix-evo logs trace [...]` | 按会话还原 AI 调用链(prompt → PreToolUse → PostToolUse → Stop) |
194
200
 
195
201
  > 占位组件 → 真组件的升级流程**不是** CLI 子命令,由
196
202
  > [`teamix-evo-manage`](../../packages/skills/src/teamix-evo-manage/SKILL.md)
@@ -103,6 +103,13 @@ type RunSkillsInitResult = {
103
103
  resources: InstalledResource[];
104
104
  addedSkillIds: string[];
105
105
  skippedSkillIds: string[];
106
+ /**
107
+ * Always `[]` for `runSkillsInit` — bulk bootstrap deliberately does not
108
+ * surface upgrade hints (only `runSkillsAdd` does, ADR 0034). Kept on
109
+ * the type so the result shape stays consistent with `RunSkillsAddResult`
110
+ * and `finalizeSkillsInstall`'s return.
111
+ */
112
+ outdatedSkills: OutdatedSkillInfo[];
106
113
  } | {
107
114
  /** Returned when a skills package is already installed and bulk has nothing new to add. */
108
115
  status: 'already-initialized';
@@ -133,6 +140,18 @@ interface RunSkillsAddOptions {
133
140
  /** Override the skills package name (defaults to "@teamix-evo/skills"). */
134
141
  packageName?: string;
135
142
  }
143
+ /**
144
+ * Detail for an already-installed skill whose locked version is older than
145
+ * the manifest's latest version. Use `skills update <id>` to upgrade.
146
+ */
147
+ interface OutdatedSkillInfo {
148
+ /** Skill id */
149
+ id: string;
150
+ /** Version recorded in `.teamix-evo/skills.lock.json` */
151
+ installed: string;
152
+ /** Version available in the upstream manifest (i.e. `npx` resolved `@latest`) */
153
+ latest: string;
154
+ }
136
155
  type RunSkillsAddResult = {
137
156
  status: 'installed';
138
157
  packageName: string;
@@ -147,8 +166,18 @@ type RunSkillsAddResult = {
147
166
  resources: InstalledResource[];
148
167
  /** Skill ids that were freshly added in this call. */
149
168
  addedSkillIds: string[];
150
- /** Skill ids that were requested but already installed; skipped. */
169
+ /**
170
+ * Skill ids that were requested but already installed at the latest version;
171
+ * nothing to do. Outdated installs are reported separately via
172
+ * {@link outdatedSkills}.
173
+ */
151
174
  skippedSkillIds: string[];
175
+ /**
176
+ * Skill ids that were requested, are already installed, but whose locked
177
+ * version is older than the manifest version. Caller should surface a hint
178
+ * recommending `skills update <id>`.
179
+ */
180
+ outdatedSkills: OutdatedSkillInfo[];
152
181
  };
153
182
  /**
154
183
  * Programmatic equivalent of `teamix-evo skills add <names...>` (ADR 0034).
@@ -390,6 +419,15 @@ interface ListVariantUiEntriesResult {
390
419
  declare function listBizUiEntries(variant: string, packageRoot?: string): Promise<ListVariantUiEntriesResult>;
391
420
  declare function listTemplatesEntries(variant: string, packageRoot?: string): Promise<ListVariantUiEntriesResult>;
392
421
 
422
+ /**
423
+ * Phase 3.E lint conflict strategies (mirrors `init-conflicts.ts`).
424
+ *
425
+ * `merge` and `backup-overwrite` both back up the existing user file before
426
+ * writing the teamix-evo template; `merge` additionally surfaces an AI-assist
427
+ * hint so the manage / code skill can guide the user through merging custom
428
+ * rules. `skip` keeps the user's file as-is and emits no template.
429
+ */
430
+ type LintConflictStrategy = 'merge' | 'backup-overwrite' | 'skip' | 'overwrite';
393
431
  interface RunLintInitOptions {
394
432
  /** Absolute project root directory. */
395
433
  projectRoot: string;
@@ -399,11 +437,43 @@ interface RunLintInitOptions {
399
437
  * installed in a later batch step.
400
438
  */
401
439
  skipInstall?: boolean;
440
+ /**
441
+ * Phase 3.E: strategy for handling existing ESLint config files.
442
+ * Defaults to `'overwrite'` (legacy behaviour); the `init` orchestrator
443
+ * passes the wizard-resolved value when consumer files are detected.
444
+ */
445
+ eslintStrategy?: LintConflictStrategy;
446
+ /**
447
+ * Phase 3.E: strategy for handling existing Stylelint config files.
448
+ */
449
+ stylelintStrategy?: LintConflictStrategy;
450
+ /**
451
+ * Phase 3.E: paths of existing ESLint configs (relative to projectRoot)
452
+ * to back up. Empty when no consumer config was detected.
453
+ */
454
+ eslintExistingPaths?: string[];
455
+ /**
456
+ * Phase 3.E: paths of existing Stylelint configs (relative to projectRoot).
457
+ */
458
+ stylelintExistingPaths?: string[];
402
459
  }
403
460
  type RunLintInitResult = {
404
461
  status: 'installed';
405
462
  eslint: boolean;
406
463
  stylelint: boolean;
464
+ /** True when the user had a custom config and asked for AI-assisted merge. */
465
+ eslintMergeRequested?: boolean;
466
+ stylelintMergeRequested?: boolean;
467
+ /** True when the strategy asked us to keep the user file untouched. */
468
+ eslintSkipped?: boolean;
469
+ stylelintSkipped?: boolean;
470
+ /**
471
+ * True when `package.json` was actually patched (lint / lint:css
472
+ * scripts inserted). Powers the project-init change ledger so the
473
+ * CLI does not report a phantom write when both scripts already
474
+ * existed.
475
+ */
476
+ packageJsonPatched?: boolean;
407
477
  } | {
408
478
  status: 'already-initialized';
409
479
  };
@@ -415,6 +485,443 @@ type RunLintInitResult = {
415
485
  */
416
486
  declare function runLintInit(options: RunLintInitOptions): Promise<RunLintInitResult>;
417
487
 
488
+ /**
489
+ * Generate `<projectRoot>/AGENTS.md` as a skill-trigger fallback (ADR 0038).
490
+ *
491
+ * The file is **regenerable**: it consolidates TRIGGER / SKIP excerpts from
492
+ * each installed SKILL.md frontmatter description into one terse index, so
493
+ * AGENTS.md-aware IDEs (Codex / Cursor / Claude Code / Qoder) preheat the
494
+ * skill activation conditions even when the user prompt does not directly
495
+ * hit the description-based trigger.
496
+ *
497
+ * Out of scope (per ADR 0038):
498
+ * - Does NOT copy skill body / rules / patterns — those stay in the skill.
499
+ * - Does NOT include `teamix-evo-manage` (entry skill, global scope, ADR 0033).
500
+ *
501
+ * Lifted from `create-teamix-evo` (v0.5) into `teamix-evo/core` so both
502
+ * `npm create teamix-evo` (scaffold path) and `teamix-evo init` (existing-
503
+ * project path, ADR 0019 task #5) emit identical AGENTS.md output.
504
+ *
505
+ * @module teamix-evo/core/agents-md
506
+ */
507
+ interface RunGenerateAgentsMdOptions {
508
+ /** Absolute path to the consumer project root. */
509
+ projectRoot: string;
510
+ /** Tokens / skills variant (e.g. "opentrek"). Used for header context. */
511
+ variant: string;
512
+ /**
513
+ * Skill ids whose `<projectRoot>/.teamix-evo/skills/<id>/SKILL.md` should be
514
+ * indexed. Caller is responsible for filtering out global-only skills
515
+ * (e.g. `teamix-evo-manage`).
516
+ */
517
+ skillIds: string[];
518
+ /**
519
+ * Reconciliation mode (Phase 2.B):
520
+ * - `'overwrite'` (default): always rewrite the full file. Pre-existing
521
+ * content is backed up and discarded.
522
+ * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed
523
+ * region. When the consumer file lacks the region, prepend a fresh
524
+ * managed block ahead of the user's content (auto-adopt). The user's
525
+ * non-managed sections are preserved.
526
+ *
527
+ * In both modes, an existing file is backed up under
528
+ * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before any mutation.
529
+ */
530
+ mode?: 'overwrite' | 'merge-managed';
531
+ }
532
+ interface RunGenerateAgentsMdResult {
533
+ /** Absolute path of the written `AGENTS.md`. */
534
+ path: string;
535
+ /** Number of skill sections rendered (missing SKILL.md degradations are still counted). */
536
+ skillCount: number;
537
+ /** Skill ids whose SKILL.md could not be read (rendered as degraded section). */
538
+ missingSkillIds: string[];
539
+ /**
540
+ * True when an existing AGENTS.md was backed up under
541
+ * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before being overwritten
542
+ * (Phase 1.A2 — full backup strategy).
543
+ */
544
+ backedUp: boolean;
545
+ /**
546
+ * Outcome of the merge step (Phase 2.B):
547
+ * - `'created'`: no AGENTS.md existed; wrote a fresh full template.
548
+ * - `'overwritten'`: existed but mode='overwrite' — full rewrite.
549
+ * - `'managed-replaced'`: mode='merge-managed' and the consumer file
550
+ * already had the `teamix-evo-skills` managed region; only that region
551
+ * was rewritten. User content outside is preserved.
552
+ * - `'managed-prepended'`: mode='merge-managed' but the consumer file
553
+ * did not yet have the managed region; a fresh block was inserted at
554
+ * the top, with the existing user content kept below.
555
+ */
556
+ merge: 'created' | 'overwritten' | 'managed-replaced' | 'managed-prepended';
557
+ }
558
+ interface SkillDescriptionParts {
559
+ /** First non-empty line(s) of `description` (the capability statement). */
560
+ capability: string;
561
+ trigger: string | null;
562
+ skip: string | null;
563
+ coordinates: string | null;
564
+ }
565
+ /**
566
+ * Generate and write the `AGENTS.md` file.
567
+ *
568
+ * Phase 2.B — reconciliation modes:
569
+ * - `'overwrite'` (default): regenerable behaviour, full rewrite.
570
+ * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed region
571
+ * so user-authored sections (project-specific guidance, design tokens,
572
+ * prompts) are never clobbered.
573
+ *
574
+ * Existing files are always backed up under `.teamix-evo/.backups/` before
575
+ * mutation (ADR 0019 §2, Phase 1.A2).
576
+ */
577
+ declare function runGenerateAgentsMd(options: RunGenerateAgentsMdOptions): Promise<RunGenerateAgentsMdResult>;
578
+ /**
579
+ * Parse a SKILL.md frontmatter description into capability / TRIGGER / SKIP /
580
+ * Coordinates parts.
581
+ *
582
+ * Why hand-rolled (no gray-matter): we only need the `description: |` block.
583
+ * The full YAML grammar is overkill and adds a runtime dep to a CLI / scaffold
584
+ * tool that should stay zero-cost. ADR 0015 keeps frontmatter shape stable.
585
+ */
586
+ declare function extractDescriptionParts(fileContent: string): SkillDescriptionParts | null;
587
+
588
+ /**
589
+ * Three branches of `teamix-evo init` decision tree (ADR 0019 D1).
590
+ *
591
+ * - `empty` : 空目录或仅含可忽略文件 → 推荐用户走 `npm create teamix-evo`(完整版)
592
+ * - `teamix-evo-installed`: 已存在 `.teamix-evo/` → 推荐 `teamix-evo update` / 卸载流程
593
+ * - `non-teamix-evo` : 已有非 teamix-evo 工程 → 走 `teamix-evo init` 普通版接入
594
+ */
595
+ type ProjectState = 'empty' | 'teamix-evo-installed' | 'non-teamix-evo';
596
+ interface ProjectStateReport {
597
+ /** Decision-tree branch the caller should take. */
598
+ state: ProjectState;
599
+ /** Absolute path that was inspected. */
600
+ cwd: string;
601
+ /** Whether `.teamix-evo/` exists at `cwd`. */
602
+ hasTeamixDir: boolean;
603
+ /** Whether `package.json` exists at `cwd`. */
604
+ hasPackageJson: boolean;
605
+ /**
606
+ * Up to 20 entries (relative to `cwd`) that caused us to consider the
607
+ * directory non-empty. Useful for explaining the decision to humans.
608
+ */
609
+ significantEntries: string[];
610
+ }
611
+ /**
612
+ * Inspect `cwd` and decide which branch of the `teamix-evo init` decision
613
+ * tree applies. Pure read-only — never mutates the filesystem.
614
+ *
615
+ * Resolution order (first match wins):
616
+ * 1. `.teamix-evo/` exists → `teamix-evo-installed`
617
+ * 2. cwd missing OR all entries are in the IGNORED_TOP_LEVEL set
618
+ * → `empty`
619
+ * 3. otherwise → `non-teamix-evo`
620
+ */
621
+ declare function detectProjectState(cwd: string): Promise<ProjectStateReport>;
622
+
623
+ /**
624
+ * The 8 categories of consumer-side files that `teamix-evo init` may
625
+ * conflict with when running against a non-teamix-evo project.
626
+ *
627
+ * See ADR 0019 D1 task #5 — these are the only files we mutate at
628
+ * `init` time, so they're the only ones we ask the user about.
629
+ */
630
+ type ConflictKey = 'agents-md' | 'components-json' | 'tailwind-config' | 'tokens' | 'index-css' | 'shadcn-source' | 'eslint-config' | 'stylelint-config';
631
+ /** Strategy options per conflict category. */
632
+ type ConflictStrategy = 'overwrite' | 'merge-managed' | 'skip' | 'diff-prompt' | 'backup-overwrite' | 'migrate' | 'coexist' | 'append' | 'skip-existing' | 'per-file-prompt' | 'merge';
633
+ interface ConflictItem {
634
+ /** Stable id for the category. */
635
+ key: ConflictKey;
636
+ /** True if at least one path in `paths` matched on disk. */
637
+ exists: boolean;
638
+ /**
639
+ * Project-relative paths that matched. Empty when `exists === false`.
640
+ * For `shadcn-source`, may contain a directory path (with trailing `/`).
641
+ */
642
+ paths: string[];
643
+ /** sha256 fingerprint of (sorted) matched contents. Omitted for directories or when nothing matched. */
644
+ fingerprint?: string;
645
+ /** Default strategy presented to the user. */
646
+ recommendedStrategy: ConflictStrategy;
647
+ /** All allowed strategies for this category, in display order. */
648
+ availableStrategies: ConflictStrategy[];
649
+ /** Category-specific metadata (e.g. detected tailwind major version). */
650
+ meta?: Record<string, unknown>;
651
+ }
652
+ interface ConflictReport {
653
+ cwd: string;
654
+ /** Always 8 items, ordered by ConflictKey enumeration above. */
655
+ items: ConflictItem[];
656
+ /** True if any item has `exists === true`. */
657
+ hasAnyConflict: boolean;
658
+ }
659
+ /**
660
+ * Inspect `cwd` for the 8 categories of files that `teamix-evo init` may
661
+ * touch. Pure read-only — never mutates the filesystem. Returns one
662
+ * `ConflictItem` per category in stable order so callers can render a
663
+ * deterministic wizard.
664
+ */
665
+ declare function detectConflicts(cwd: string): Promise<ConflictReport>;
666
+
667
+ /**
668
+ * Final answers produced by the init wizard. Every consumer of `teamix-evo
669
+ * init` (orchestrator + later sub-commands) reads from this object exclusively
670
+ * — flags / prompts must not be re-evaluated downstream (silent sub-commands).
671
+ */
672
+ interface InitWizardAnswers {
673
+ variant: string;
674
+ ides: SkillIde[];
675
+ scope: SkillScope;
676
+ withLint: boolean;
677
+ withUi: boolean;
678
+ /** 'baseline' = preset 推荐组件子集;'all' = 全量装 */
679
+ uiSelection: 'baseline' | 'all';
680
+ withBizUi: boolean;
681
+ /**
682
+ * 每类冲突文件的最终策略。键是 6 类 ConflictKey,值是 user-chosen
683
+ * `ConflictStrategy`。当对应 ConflictItem.exists === false 时,值默认为
684
+ * `'overwrite'`(即首次写入)。
685
+ */
686
+ conflictDecisions: Record<ConflictKey, ConflictStrategy>;
687
+ }
688
+
689
+ /** Result of `createSnapshot` when a snapshot was actually taken. */
690
+ interface SnapshotResult {
691
+ /** Filesystem-safe UTC timestamp identifier (e.g. `2026-06-11T20-59-03-000Z`). */
692
+ ts: string;
693
+ /** Absolute path to the snapshot directory. */
694
+ path: string;
695
+ }
696
+
697
+ type FileChangeKind = 'created' | 'modified' | 'backed-up' | 'deleted';
698
+ interface FileChange {
699
+ kind: FileChangeKind;
700
+ /** Project-root-relative path, posix style (forward slashes). */
701
+ path: string;
702
+ /** Originating pipeline step (free-form to avoid coupling on `ProjectInitStepName`). */
703
+ step: string;
704
+ /** Optional human-readable note (e.g. `frozen` / `regenerable` / `managed`). */
705
+ detail?: string;
706
+ }
707
+
708
+ /**
709
+ * Programmatic orchestrator for `teamix-evo init` (existing-project adoption).
710
+ *
711
+ * Consumes {@link InitWizardAnswers} produced by `runInitWizard` and drives
712
+ * the existing core sub-commands (`runTokensInit`, `runSkillsAdd`,
713
+ * `runGenerateAgentsMd`, `runUiInit`, `runUiAdd`, `runLintInit`) in a fixed
714
+ * order. Sub-commands are invoked silently — no interactive prompts here.
715
+ *
716
+ * Conflict handling:
717
+ * - `conflictDecisions[key] === 'skip'` skips the corresponding step entirely.
718
+ * - `'overwrite'` is the trivial path (the underlying core APIs already write).
719
+ * - `'merge-managed'` (agents-md) is implemented today via
720
+ * `runGenerateAgentsMd` which writes managed regions natively.
721
+ * - `'skip-existing'` (shadcn-source) maps to `runUiAdd({ overwrite: false })`,
722
+ * the existing default.
723
+ * - All other strategies (`diff-prompt`, `backup-overwrite`, `migrate`,
724
+ * `coexist`, `append`, `per-file-prompt`) require the managed-region engine
725
+ * from batch 4 — they are recorded to `pendingConflictWork` so the CLI
726
+ * surface can guide the user to the followup `teamix-evo conflict resolve`
727
+ * step (post-batch-4).
728
+ *
729
+ * No interactive prompts, no `process.exit`. Throws on hard failure (P8).
730
+ */
731
+
732
+ type ProjectInitStepName = 'tokens' | 'skills' | 'agents-md' | 'ui-init' | 'ui-add' | 'lint';
733
+ type ProjectInitStepStatus = 'ok' | 'skip' | 'fail' | 'planned';
734
+ interface ProjectInitStep {
735
+ name: ProjectInitStepName;
736
+ status: ProjectInitStepStatus;
737
+ detail?: string;
738
+ /**
739
+ * Files this step touched (Phase 1.A1). Empty when the step skipped or
740
+ * failed before any I/O. The `kind` is `created` by default; the orchestrator
741
+ * upgrades entries to `modified` post-hoc by checking the backup ledger
742
+ * (`.teamix-evo/.backups/`).
743
+ */
744
+ changes?: FileChange[];
745
+ }
746
+ interface PendingConflictWork {
747
+ key: ConflictKey;
748
+ strategy: ConflictStrategy;
749
+ reason: string;
750
+ }
751
+ interface ResumeHint {
752
+ /** The first step that failed (caller resumes from here). */
753
+ failedAt: ProjectInitStepName;
754
+ /** Steps already finished (status === 'ok'); will short-circuit on resume. */
755
+ completed: ProjectInitStepName[];
756
+ /** All steps that ended in fail status. */
757
+ failed: ProjectInitStepName[];
758
+ /** Human-readable error from the first failed step. */
759
+ error: string;
760
+ /**
761
+ * Suggested CLI command to resume. Today this is just `teamix-evo init`
762
+ * itself — every sub-step is idempotent (returns `already-initialized`
763
+ * when the matching state file already exists), so a re-run continues
764
+ * from the failure point automatically. Future batches may grow a
765
+ * dedicated `--resume` flag with a richer recovery model (batch 3).
766
+ */
767
+ resumeCommand: string;
768
+ }
769
+ interface RunProjectInitOptions {
770
+ /** Absolute project root (existing repo to adopt teamix-evo into). */
771
+ projectRoot: string;
772
+ /** Wizard outcome (single source of truth for every silent sub-command). */
773
+ answers: InitWizardAnswers;
774
+ /**
775
+ * Override the resolved UI entry list. When provided, replaces the
776
+ * `answers.uiSelection`-driven list (`'baseline'` / `'all'`). Useful for
777
+ * tests and for callers that want to install a custom subset.
778
+ */
779
+ uiEntries?: string[];
780
+ /**
781
+ * If true, skip `npm install` for lint deps. Defaults to `false` so lint
782
+ * works out of the box; pass `true` from the create scaffold which installs
783
+ * everything in one batch.
784
+ */
785
+ skipInstall?: boolean;
786
+ /**
787
+ * Legacy token CSS files (paths relative to `projectRoot`) detected by
788
+ * `detectConflicts` for the `tokens` key. When `conflictDecisions.tokens`
789
+ * is `'migrate'` and this list is non-empty, the orchestrator appends
790
+ * each file's content into `tokens/tokens.overrides.css` and backs the
791
+ * legacy files up to `.teamix-evo/.backups/` (W1.4 of the manage-entry
792
+ * plan; see [`legacy-tokens-migrate`](./legacy-tokens-migrate.ts)).
793
+ *
794
+ * Ignored for any other `tokens` decision. The caller (init command) is
795
+ * responsible for filtering out paths already inside `tokens/`.
796
+ */
797
+ legacyTokensPaths?: string[];
798
+ /**
799
+ * Phase 3.E: existing ESLint config paths (relative to `projectRoot`)
800
+ * detected by `detectConflicts` for the `eslint-config` key. Used to
801
+ * back up the consumer's file before writing the teamix-evo template,
802
+ * and to gate the `merge` / `backup-overwrite` / `skip` strategies in
803
+ * `runLintInit`.
804
+ */
805
+ legacyEslintPaths?: string[];
806
+ /**
807
+ * Phase 3.E: existing Stylelint config paths (relative to `projectRoot`).
808
+ */
809
+ legacyStylelintPaths?: string[];
810
+ /** Step-level progress hook (caller controls presentation). */
811
+ onStep?: (step: ProjectInitStep) => void;
812
+ /**
813
+ * If true, plan-only mode: compute the full step list without running any
814
+ * sub-command. Returns each step with `status: 'planned'`.
815
+ */
816
+ dryRun?: boolean;
817
+ }
818
+ interface RunProjectInitResult {
819
+ status: 'installed' | 'partial' | 'dry-run';
820
+ steps: ProjectInitStep[];
821
+ /** Conflicts whose strategy needs the post-batch-4 managed-region engine. */
822
+ pendingConflictWork: PendingConflictWork[];
823
+ /**
824
+ * Aggregated, classified file-change ledger covering every step
825
+ * (Phase 1.A1). Backup entries are surfaced as `kind: 'backed-up'` so the
826
+ * CLI can render a four-bucket summary (新建 / 修改 / 备份 / 删除).
827
+ */
828
+ changes: FileChange[];
829
+ /**
830
+ * Present when at least one step ended in `fail`. Lets the CLI surface a
831
+ * structured recovery message instead of just a stack-trace, and gives
832
+ * programmatic consumers a deterministic field to branch on.
833
+ */
834
+ resumeHint?: ResumeHint;
835
+ /**
836
+ * Pre-init snapshot of `.teamix-evo/`, captured automatically before any
837
+ * file is written ([ADR 0019](../../../../docs/adr/0019-project-upgrade-flow.md) §2).
838
+ *
839
+ * - `null` on first-ever init (`.teamix-evo/` did not yet exist) and on
840
+ * `dryRun`.
841
+ * - Failure to capture a snapshot is **non-fatal** — surfaced via
842
+ * {@link snapshotError} so the CLI can warn the user. The init pipeline
843
+ * itself still runs.
844
+ */
845
+ snapshot?: SnapshotResult | null;
846
+ /** Reason a snapshot capture failed (best-effort — never blocks init). */
847
+ snapshotError?: string;
848
+ }
849
+ /**
850
+ * Existing-project init pipeline.
851
+ *
852
+ * Order:
853
+ * 1. tokens init (auto-installs `teamix-evo-design-${variant}` skill)
854
+ * 2. skills add (`teamix-evo-code-${variant}`; entry skill is global, ADR 0033)
855
+ * 3. AGENTS.md (skill trigger fallback, ADR 0038)
856
+ * 4. ui init + ui add (gated by `withUi`)
857
+ * 5. lint init (gated by `withLint`)
858
+ */
859
+ declare function runProjectInit(options: RunProjectInitOptions): Promise<RunProjectInitResult>;
860
+
861
+ type ProjectUpdateStepName = 'tokens' | 'skills' | 'ui' | 'biz-ui';
862
+ type ProjectUpdateStepStatus = 'ok' | 'skip' | 'fail' | 'planned';
863
+ interface ProjectUpdateStep {
864
+ name: ProjectUpdateStepName;
865
+ status: ProjectUpdateStepStatus;
866
+ detail?: string;
867
+ }
868
+ interface ProjectUpdateResumeHint {
869
+ /** The first step that failed (caller resumes from here). */
870
+ failedAt: ProjectUpdateStepName;
871
+ /** Steps already finished (status === 'ok'); will short-circuit on resume. */
872
+ completed: ProjectUpdateStepName[];
873
+ /** All steps that ended in fail status. */
874
+ failed: ProjectUpdateStepName[];
875
+ /** Human-readable error from the first failed step. */
876
+ error: string;
877
+ /**
878
+ * Suggested CLI command to resume. Today this is just `teamix-evo update`
879
+ * itself — every sub-step is idempotent (version-diff short-circuits when
880
+ * up-to-date), so a re-run continues from the failure point automatically.
881
+ */
882
+ resumeCommand: string;
883
+ }
884
+ interface RunProjectUpdateOptions {
885
+ /** Absolute project root (must already be teamix-evo-installed). */
886
+ projectRoot: string;
887
+ /**
888
+ * If true, plan-only mode: compute version deltas without writing any
889
+ * file. Returns each step with `status: 'planned'`.
890
+ */
891
+ dryRun?: boolean;
892
+ /** Step-level progress hook (caller controls presentation). */
893
+ onStep?: (step: ProjectUpdateStep) => void;
894
+ /** Override the tokens package name (defaults to `@teamix-evo/tokens`). */
895
+ tokensPackageName?: string;
896
+ /** Override the skills package name (defaults to `@teamix-evo/skills`). */
897
+ skillsPackageName?: string;
898
+ }
899
+ type RunProjectUpdateResult = {
900
+ status: 'not-initialized';
901
+ } | {
902
+ status: 'up-to-date' | 'updated' | 'partial' | 'dry-run';
903
+ steps: ProjectUpdateStep[];
904
+ resumeHint?: ProjectUpdateResumeHint;
905
+ /**
906
+ * Pre-update snapshot of `.teamix-evo/` ([ADR 0019](../../../../docs/adr/0019-project-upgrade-flow.md) §2).
907
+ * `null` on `dryRun`. Best-effort — capture failures surface via
908
+ * {@link snapshotError} but never abort the pipeline.
909
+ */
910
+ snapshot?: SnapshotResult | null;
911
+ /** Reason a snapshot capture failed (best-effort — never blocks update). */
912
+ snapshotError?: string;
913
+ };
914
+ /**
915
+ * Post-init refresh pipeline.
916
+ *
917
+ * Order:
918
+ * 1. tokens update (regenerable rewrite + frozen preserved — ADR 0003 三态)
919
+ * 2. skills update (lock ∩ scope ∩ version-diff short-circuit — ADR 0035)
920
+ *
921
+ * Re-runs are safe: each sub-step short-circuits when already at latest.
922
+ */
923
+ declare function runProjectUpdate(options: RunProjectUpdateOptions): Promise<RunProjectUpdateResult>;
924
+
418
925
  interface InstallOptions {
419
926
  /** Project root directory */
420
927
  projectRoot: string;
@@ -443,7 +950,7 @@ declare function installResources(options: InstallOptions): Promise<InstallResul
443
950
  *
444
951
  * Two-stage flow:
445
952
  * 1. **writeSkillSources** — render upstream `<packageRoot>/<skill.source>` and
446
- * write to `<projectRoot>/.teamix-evo/skills/<id>/` (the consumer-side
953
+ * write to `<projectRoot>/.teamix-evo/skills-source/<id>/` (the consumer-side
447
954
  * source of truth, regenerable, in git).
448
955
  * 2. **syncSkillsToIdes** — pure byte-for-byte copy from source dir to each
449
956
  * requested IDE mirror path (`.qoder/skills/<id>/`, `.claude/skills/<id>/`).
@@ -662,4 +1169,4 @@ declare function readInstalledManifest(projectRoot: string): Promise<InstalledMa
662
1169
  */
663
1170
  declare function writeInstalledManifest(projectRoot: string, manifest: InstalledManifest): Promise<void>;
664
1171
 
665
- export { DEFAULT_UI_ALIASES, DEFAULT_UI_ICON_LIBRARY, type InstallOptions, type InstallResult, type ListVariantUiEntriesResult, type ListVariantUiResult, type ListVariantsResult, type RunLintInitOptions, type RunLintInitResult, type RunSkillsAddOptions, type RunSkillsAddResult, type RunSkillsInitOptions, type RunSkillsInitResult, type RunSkillsUpdateOptions, type RunSkillsUpdateResult, type RunTokensInitOptions, type RunTokensInitResult, type RunUiAddOptions, type RunUiAddResult, type RunUiInitOptions, type RunUiInitResult, type RunUiListOptions, type RunUiListResult, type RunVariantUiAddOptions, type RunVariantUiAddResult, type SkillInstallOptions, type SkillInstallResult, type SkillSyncOptions, type SkillSyncResult, type SkillUpdateOptions, type SkillUpdateResult, type UiEntryListItem, type UiInstallOptions, type UiInstallResult, type UpdatePlanItem, ensureTeamixDir, getTeamixDir, installResources, installSkills, installUiEntries, listBizUiEntries, listBizUiVariants, listTemplatesEntries, listTemplatesVariants, listTokenVariants, loadSkillsData, loadUiData, loadVariantData, readInstalledManifest, readProjectConfig, removeSkillFiles, removeUiFiles, runBizUiAdd, runLintInit, runSkillsAdd, runSkillsInit, runSkillsUpdate, runTemplatesAdd, runTokensInit, runUiAdd, runUiInit, runUiList, syncSkillsToIdes, updateSkills, writeInstalledManifest, writeProjectConfig };
1172
+ export { type ConflictItem, type ConflictKey, type ConflictReport, type ConflictStrategy, DEFAULT_UI_ALIASES, DEFAULT_UI_ICON_LIBRARY, type InstallOptions, type InstallResult, type ListVariantUiEntriesResult, type ListVariantUiResult, type ListVariantsResult, type PendingConflictWork, type ProjectInitStep, type ProjectInitStepName, type ProjectInitStepStatus, type ProjectState, type ProjectStateReport, type ProjectUpdateResumeHint, type ProjectUpdateStep, type ProjectUpdateStepName, type ProjectUpdateStepStatus, type ResumeHint, type RunGenerateAgentsMdOptions, type RunGenerateAgentsMdResult, type RunLintInitOptions, type RunLintInitResult, type RunProjectInitOptions, type RunProjectInitResult, type RunProjectUpdateOptions, type RunProjectUpdateResult, type RunSkillsAddOptions, type RunSkillsAddResult, type RunSkillsInitOptions, type RunSkillsInitResult, type RunSkillsUpdateOptions, type RunSkillsUpdateResult, type RunTokensInitOptions, type RunTokensInitResult, type RunUiAddOptions, type RunUiAddResult, type RunUiInitOptions, type RunUiInitResult, type RunUiListOptions, type RunUiListResult, type RunVariantUiAddOptions, type RunVariantUiAddResult, type SkillInstallOptions, type SkillInstallResult, type SkillSyncOptions, type SkillSyncResult, type SkillUpdateOptions, type SkillUpdateResult, type UiEntryListItem, type UiInstallOptions, type UiInstallResult, type UpdatePlanItem, detectConflicts, detectProjectState, ensureTeamixDir, extractDescriptionParts, getTeamixDir, installResources, installSkills, installUiEntries, listBizUiEntries, listBizUiVariants, listTemplatesEntries, listTemplatesVariants, listTokenVariants, loadSkillsData, loadUiData, loadVariantData, readInstalledManifest, readProjectConfig, removeSkillFiles, removeUiFiles, runBizUiAdd, runGenerateAgentsMd, runLintInit, runProjectInit, runProjectUpdate, runSkillsAdd, runSkillsInit, runSkillsUpdate, runTemplatesAdd, runTokensInit, runUiAdd, runUiInit, runUiList, syncSkillsToIdes, updateSkills, writeInstalledManifest, writeProjectConfig };