teamix-evo 0.8.0 → 0.10.1

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,34 +167,41 @@ TEAMIX_DEBUG=1 teamix-evo tokens init opentrek
167
167
 
168
168
  ## 命令参考
169
169
 
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 skills init` | 自举 skills(按 variant + scope 全装 ADR 0034) |
182
- | `teamix-evo skills add <name...>` | 增量装指定 skill(`<name...>` 必填) |
183
- | `teamix-evo skills list` | 列出所有 skill 的安装状态 |
184
- | `teamix-evo skills update [name...] [--dry-run]` | 升级 skills(双闸 + version 短路 ADR 0035) |
185
- | `teamix-evo skills sync [name...]` | IDE 镜像(漂移恢复用) |
186
- | `teamix-evo skills doctor` | 检测源/镜像漂移(ADR 0013) |
187
- | `teamix-evo skills uninstall` | 卸载 skills( + 镜像 + lock) |
188
- | `teamix-evo ui init` | 初始化 ui 配置(aliases / iconLibrary / tsx / rsc) |
189
- | `teamix-evo ui add <id...>` | 安装指定 ui 组件源码 |
190
- | `teamix-evo ui list [--installed]` | 列出可用/已安装 ui 组件 |
191
- | `teamix-evo biz-ui list-variants` | 列出 biz-ui 包内提供的业务变体 |
192
- | `teamix-evo biz-ui add <id...> --variant <name>` | 安装变体感知业务组件(`--variant` 必填) |
193
- | `teamix-evo templates list-variants` | 列出 templates 包内提供的页面模板变体 |
194
- | `teamix-evo templates add <id...> --variant <name>` | 安装变体感知页面模板(`--variant` 必填) |
195
- | `teamix-evo lint init [-y]` | 一键安装 ESLint + Stylelint token-discipline 规则集 |
196
- | `teamix-evo logs analyze [...]` | 分析 vibe-logger AI 调用链(`.log/ai/**/*.jsonl`) |
197
- | `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 tokens diagnose` | 诊断 tokens 使用情况,生成分级报告(L1-L3)+ `.treatment-plan.md` |
183
+ | `teamix-evo tokens treat [--lock-baseline] [--apply]` | 一键 token 治理流水线:lint → codemod → lint → 报告 → 可选锁定 baseline |
184
+ | `teamix-evo tokens codemod [name] [--apply] [--list]` | 执行指定 token codemod(5 个可用:hsl-to-v4 / hex-to-token / tw-scale-to-semantic / space-to-gap / arbitrary-to-token) |
185
+ | `teamix-evo tokens reflect [--min-frequency <n>]` | 扫描重复色值,推荐新增项目级 token(反哺 overrides.css) |
186
+ | `teamix-evo tokens baseline-check` | 对比 baseline 检查 token 违规是否超标(CI 友好,exitCode=1 on fail) |
187
+ | `teamix-evo skills init` | 自举 skills( variant + scope 全装 — ADR 0034) |
188
+ | `teamix-evo skills add <name...>` | 增量装指定 skill(`<name...>` 必填) |
189
+ | `teamix-evo skills list` | 列出所有 skill 的安装状态 |
190
+ | `teamix-evo skills update [name...] [--dry-run]` | 升级 skills(双闸 + version 短路 — ADR 0035) |
191
+ | `teamix-evo skills sync [name...]` | IDE 镜像(漂移恢复用) |
192
+ | `teamix-evo skills doctor` | 检测源/镜像漂移(ADR 0013) |
193
+ | `teamix-evo skills uninstall` | 卸载 skills(源 + 镜像 + lock) |
194
+ | `teamix-evo ui init` | 初始化 ui 配置(aliases / iconLibrary / tsx / rsc) |
195
+ | `teamix-evo ui add <id...>` | 安装指定 ui 组件源码 |
196
+ | `teamix-evo ui list [--installed]` | 列出可用/已安装 ui 组件 |
197
+ | `teamix-evo ui promote-to-biz <id...>` | ui 组件提升为业务组件(8 模式:Coexist/Preset/Wrapper/Compose/Variant/Fork/TokenOnly/ManualReview) |
198
+ | `teamix-evo biz-ui list-variants` | 列出 biz-ui 包内提供的业务变体 |
199
+ | `teamix-evo biz-ui add <id...> --variant <name>` | 安装变体感知业务组件(`--variant` 必填) |
200
+ | `teamix-evo templates list-variants` | 列出 templates 包内提供的页面模板变体 |
201
+ | `teamix-evo templates add <id...> --variant <name>` | 安装变体感知页面模板(`--variant` 必填) |
202
+ | `teamix-evo lint init [-y]` | 一键安装 ESLint + Stylelint token-discipline 规则集 |
203
+ | `teamix-evo logs analyze [...]` | 分析 vibe-logger AI 调用链(`.log/ai/**/*.jsonl`) |
204
+ | `teamix-evo logs trace [...]` | 按会话还原 AI 调用链(prompt → PreToolUse → PostToolUse → Stop) |
198
205
 
199
206
  > 占位组件 → 真组件的升级流程**不是** CLI 子命令,由
200
207
  > [`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,49 @@ 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;
477
+ /**
478
+ * True when the consumer's existing stylelint config was kept (skip /
479
+ * merge) and does not extend a teamix-evo preset — token definition
480
+ * files may trigger false-positive lint errors without `ignoreFiles`.
481
+ */
482
+ stylelintIgnoreFilesWarning?: boolean;
407
483
  } | {
408
484
  status: 'already-initialized';
409
485
  };
@@ -445,14 +521,45 @@ interface RunGenerateAgentsMdOptions {
445
521
  * (e.g. `teamix-evo-manage`).
446
522
  */
447
523
  skillIds: string[];
524
+ /**
525
+ * Reconciliation mode (Phase 2.B):
526
+ * - `'overwrite'` (default): always rewrite the full file. Pre-existing
527
+ * content is backed up and discarded.
528
+ * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed
529
+ * region. When the consumer file lacks the region, prepend a fresh
530
+ * managed block ahead of the user's content (auto-adopt). The user's
531
+ * non-managed sections are preserved.
532
+ *
533
+ * In both modes, an existing file is backed up under
534
+ * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before any mutation.
535
+ */
536
+ mode?: 'overwrite' | 'merge-managed';
448
537
  }
449
538
  interface RunGenerateAgentsMdResult {
450
539
  /** Absolute path of the written `AGENTS.md`. */
451
540
  path: string;
452
- /** Number of skill sections rendered (excludes missing SKILL.md degradations are still counted). */
541
+ /** Number of skill sections rendered (missing SKILL.md degradations are still counted). */
453
542
  skillCount: number;
454
543
  /** Skill ids whose SKILL.md could not be read (rendered as degraded section). */
455
544
  missingSkillIds: string[];
545
+ /**
546
+ * True when an existing AGENTS.md was backed up under
547
+ * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before being overwritten
548
+ * (Phase 1.A2 — full backup strategy).
549
+ */
550
+ backedUp: boolean;
551
+ /**
552
+ * Outcome of the merge step (Phase 2.B):
553
+ * - `'created'`: no AGENTS.md existed; wrote a fresh full template.
554
+ * - `'overwritten'`: existed but mode='overwrite' — full rewrite.
555
+ * - `'managed-replaced'`: mode='merge-managed' and the consumer file
556
+ * already had the `teamix-evo-skills` managed region; only that region
557
+ * was rewritten. User content outside is preserved.
558
+ * - `'managed-prepended'`: mode='merge-managed' but the consumer file
559
+ * did not yet have the managed region; a fresh block was inserted at
560
+ * the top, with the existing user content kept below.
561
+ */
562
+ merge: 'created' | 'overwritten' | 'managed-replaced' | 'managed-prepended';
456
563
  }
457
564
  interface SkillDescriptionParts {
458
565
  /** First non-empty line(s) of `description` (the capability statement). */
@@ -462,8 +569,16 @@ interface SkillDescriptionParts {
462
569
  coordinates: string | null;
463
570
  }
464
571
  /**
465
- * Generate and write the `AGENTS.md` file. Idempotent — repeated invocations
466
- * fully overwrite the file (regenerable per ADR 0038 §4).
572
+ * Generate and write the `AGENTS.md` file.
573
+ *
574
+ * Phase 2.B — reconciliation modes:
575
+ * - `'overwrite'` (default): regenerable behaviour, full rewrite.
576
+ * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed region
577
+ * so user-authored sections (project-specific guidance, design tokens,
578
+ * prompts) are never clobbered.
579
+ *
580
+ * Existing files are always backed up under `.teamix-evo/.backups/` before
581
+ * mutation (ADR 0019 §2, Phase 1.A2).
467
582
  */
468
583
  declare function runGenerateAgentsMd(options: RunGenerateAgentsMdOptions): Promise<RunGenerateAgentsMdResult>;
469
584
  /**
@@ -512,15 +627,15 @@ interface ProjectStateReport {
512
627
  declare function detectProjectState(cwd: string): Promise<ProjectStateReport>;
513
628
 
514
629
  /**
515
- * The 6 categories of consumer-side files that `teamix-evo init` may
630
+ * The 8 categories of consumer-side files that `teamix-evo init` may
516
631
  * conflict with when running against a non-teamix-evo project.
517
632
  *
518
633
  * See ADR 0019 D1 task #5 — these are the only files we mutate at
519
634
  * `init` time, so they're the only ones we ask the user about.
520
635
  */
521
- type ConflictKey = 'agents-md' | 'components-json' | 'tailwind-config' | 'tokens' | 'index-css' | 'shadcn-source';
636
+ type ConflictKey = 'agents-md' | 'components-json' | 'tailwind-config' | 'tokens' | 'index-css' | 'shadcn-source' | 'eslint-config' | 'stylelint-config';
522
637
  /** Strategy options per conflict category. */
523
- type ConflictStrategy = 'overwrite' | 'merge-managed' | 'skip' | 'diff-prompt' | 'backup-overwrite' | 'migrate' | 'coexist' | 'append' | 'skip-existing' | 'per-file-prompt';
638
+ type ConflictStrategy = 'overwrite' | 'merge-managed' | 'skip' | 'diff-prompt' | 'backup-overwrite' | 'migrate' | 'coexist' | 'append' | 'skip-existing' | 'per-file-prompt' | 'merge';
524
639
  interface ConflictItem {
525
640
  /** Stable id for the category. */
526
641
  key: ConflictKey;
@@ -542,13 +657,13 @@ interface ConflictItem {
542
657
  }
543
658
  interface ConflictReport {
544
659
  cwd: string;
545
- /** Always 6 items, ordered by ConflictKey enumeration above. */
660
+ /** Always 8 items, ordered by ConflictKey enumeration above. */
546
661
  items: ConflictItem[];
547
662
  /** True if any item has `exists === true`. */
548
663
  hasAnyConflict: boolean;
549
664
  }
550
665
  /**
551
- * Inspect `cwd` for the 6 categories of files that `teamix-evo init` may
666
+ * Inspect `cwd` for the 8 categories of files that `teamix-evo init` may
552
667
  * touch. Pure read-only — never mutates the filesystem. Returns one
553
668
  * `ConflictItem` per category in stable order so callers can render a
554
669
  * deterministic wizard.
@@ -577,6 +692,33 @@ interface InitWizardAnswers {
577
692
  conflictDecisions: Record<ConflictKey, ConflictStrategy>;
578
693
  }
579
694
 
695
+ interface UiConflictEntry {
696
+ /** UI entry id from manifest (e.g. "button") */
697
+ id: string;
698
+ /** Absolute path on disk that conflicts */
699
+ targetPath: string;
700
+ /** Project-relative posix path for display */
701
+ relativePath: string;
702
+ /**
703
+ * Heuristic guess: true when the existing file looks like an unmodified
704
+ * shadcn/ui original (no `data-slot` attribute from teamix-evo).
705
+ * v1 uses filename + content heuristics; future versions may hash-compare.
706
+ */
707
+ isShadcnOriginal: boolean;
708
+ }
709
+ interface UiConflictReport {
710
+ /** Entries whose target file already exists on disk */
711
+ conflictEntries: UiConflictEntry[];
712
+ /** Number of manifest entries with no on-disk conflict */
713
+ unconflictedTargets: number;
714
+ /** Total manifest entries checked */
715
+ totalEntries: number;
716
+ /** True when at least one conflict exists — caller should block */
717
+ shouldBlock: boolean;
718
+ /** Distinct target alias directories that have conflicts */
719
+ conflictDirs: string[];
720
+ }
721
+
580
722
  /** Result of `createSnapshot` when a snapshot was actually taken. */
581
723
  interface SnapshotResult {
582
724
  /** Filesystem-safe UTC timestamp identifier (e.g. `2026-06-11T20-59-03-000Z`). */
@@ -585,6 +727,17 @@ interface SnapshotResult {
585
727
  path: string;
586
728
  }
587
729
 
730
+ type FileChangeKind = 'created' | 'modified' | 'backed-up' | 'deleted';
731
+ interface FileChange {
732
+ kind: FileChangeKind;
733
+ /** Project-root-relative path, posix style (forward slashes). */
734
+ path: string;
735
+ /** Originating pipeline step (free-form to avoid coupling on `ProjectInitStepName`). */
736
+ step: string;
737
+ /** Optional human-readable note (e.g. `frozen` / `regenerable` / `managed`). */
738
+ detail?: string;
739
+ }
740
+
588
741
  /**
589
742
  * Programmatic orchestrator for `teamix-evo init` (existing-project adoption).
590
743
  *
@@ -609,12 +762,31 @@ interface SnapshotResult {
609
762
  * No interactive prompts, no `process.exit`. Throws on hard failure (P8).
610
763
  */
611
764
 
612
- type ProjectInitStepName = 'tokens' | 'skills' | 'agents-md' | 'ui-init' | 'ui-add' | 'lint';
765
+ /**
766
+ * Strategy for handling UI component conflicts when existing shadcn/ui
767
+ * components are found in the target project.
768
+ *
769
+ * - `isolate-progressive` (Path A): move existing → shadcn-ui/, install
770
+ * fresh teamix-evo components into ui/, rewrite imports, let user
771
+ * migrate at their own pace.
772
+ * - `isolate-aggressive` (Path C): same as A + immediately generate
773
+ * upgrade staging so user can batch-replace.
774
+ * - `frozen-skip`: legacy behaviour — skip existing files, no migration.
775
+ */
776
+ type UiConflictStrategy = 'isolate-progressive' | 'isolate-aggressive' | 'frozen-skip';
777
+ type ProjectInitStepName = 'tokens' | 'skills' | 'agents-md' | 'ui-init' | 'ui-add' | 'lint' | 'gitignore';
613
778
  type ProjectInitStepStatus = 'ok' | 'skip' | 'fail' | 'planned';
614
779
  interface ProjectInitStep {
615
780
  name: ProjectInitStepName;
616
781
  status: ProjectInitStepStatus;
617
782
  detail?: string;
783
+ /**
784
+ * Files this step touched (Phase 1.A1). Empty when the step skipped or
785
+ * failed before any I/O. The `kind` is `created` by default; the orchestrator
786
+ * upgrades entries to `modified` post-hoc by checking the backup ledger
787
+ * (`.teamix-evo/.backups/`).
788
+ */
789
+ changes?: FileChange[];
618
790
  }
619
791
  interface PendingConflictWork {
620
792
  key: ConflictKey;
@@ -668,6 +840,30 @@ interface RunProjectInitOptions {
668
840
  * responsible for filtering out paths already inside `tokens/`.
669
841
  */
670
842
  legacyTokensPaths?: string[];
843
+ /**
844
+ * Phase 3.E: existing ESLint config paths (relative to `projectRoot`)
845
+ * detected by `detectConflicts` for the `eslint-config` key. Used to
846
+ * back up the consumer's file before writing the teamix-evo template,
847
+ * and to gate the `merge` / `backup-overwrite` / `skip` strategies in
848
+ * `runLintInit`.
849
+ */
850
+ legacyEslintPaths?: string[];
851
+ /**
852
+ * Phase 3.E: existing Stylelint config paths (relative to `projectRoot`).
853
+ */
854
+ legacyStylelintPaths?: string[];
855
+ /**
856
+ * UI conflict resolution strategy. When omitted AND conflicts are
857
+ * detected, the orchestrator returns `uiDecisionRequired` so the
858
+ * caller can prompt the user. When `-y` (non-interactive), defaults
859
+ * to `'isolate-progressive'`.
860
+ */
861
+ uiConflictStrategy?: UiConflictStrategy;
862
+ /**
863
+ * When true, treat the invocation as non-interactive (`-y` flag).
864
+ * Affects default conflict strategy selection.
865
+ */
866
+ nonInteractive?: boolean;
671
867
  /** Step-level progress hook (caller controls presentation). */
672
868
  onStep?: (step: ProjectInitStep) => void;
673
869
  /**
@@ -676,11 +872,32 @@ interface RunProjectInitOptions {
676
872
  */
677
873
  dryRun?: boolean;
678
874
  }
875
+ /**
876
+ * Returned when UI conflicts are detected and no `uiConflictStrategy` was
877
+ * provided. The caller should present the options to the user and re-invoke
878
+ * `runProjectInit` with the chosen strategy.
879
+ */
880
+ interface UiDecisionRequired {
881
+ /** The full conflict report for display */
882
+ report: UiConflictReport;
883
+ /** Available strategies with human-readable descriptions */
884
+ options: Array<{
885
+ strategy: UiConflictStrategy;
886
+ label: string;
887
+ description: string;
888
+ }>;
889
+ }
679
890
  interface RunProjectInitResult {
680
891
  status: 'installed' | 'partial' | 'dry-run';
681
892
  steps: ProjectInitStep[];
682
893
  /** Conflicts whose strategy needs the post-batch-4 managed-region engine. */
683
894
  pendingConflictWork: PendingConflictWork[];
895
+ /**
896
+ * Aggregated, classified file-change ledger covering every step
897
+ * (Phase 1.A1). Backup entries are surfaced as `kind: 'backed-up'` so the
898
+ * CLI can render a four-bucket summary (新建 / 修改 / 备份 / 删除).
899
+ */
900
+ changes: FileChange[];
684
901
  /**
685
902
  * Present when at least one step ended in `fail`. Lets the CLI surface a
686
903
  * structured recovery message instead of just a stack-trace, and gives
@@ -700,6 +917,12 @@ interface RunProjectInitResult {
700
917
  snapshot?: SnapshotResult | null;
701
918
  /** Reason a snapshot capture failed (best-effort — never blocks init). */
702
919
  snapshotError?: string;
920
+ /**
921
+ * Present when UI conflicts are detected and no `uiConflictStrategy`
922
+ * was provided (interactive mode). Caller should prompt the user with
923
+ * `options`, then re-invoke with the chosen strategy.
924
+ */
925
+ uiDecisionRequired?: UiDecisionRequired;
703
926
  }
704
927
  /**
705
928
  * Existing-project init pipeline.
@@ -805,7 +1028,7 @@ declare function installResources(options: InstallOptions): Promise<InstallResul
805
1028
  *
806
1029
  * Two-stage flow:
807
1030
  * 1. **writeSkillSources** — render upstream `<packageRoot>/<skill.source>` and
808
- * write to `<projectRoot>/.teamix-evo/skills/<id>/` (the consumer-side
1031
+ * write to `<projectRoot>/.teamix-evo/skills-source/<id>/` (the consumer-side
809
1032
  * source of truth, regenerable, in git).
810
1033
  * 2. **syncSkillsToIdes** — pure byte-for-byte copy from source dir to each
811
1034
  * requested IDE mirror path (`.qoder/skills/<id>/`, `.claude/skills/<id>/`).