yjcli 0.1.3__tar.gz → 0.2.0__tar.gz

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.
Files changed (55) hide show
  1. {yjcli-0.1.3 → yjcli-0.2.0}/PKG-INFO +7 -4
  2. {yjcli-0.1.3 → yjcli-0.2.0}/README.md +6 -3
  3. {yjcli-0.1.3 → yjcli-0.2.0}/pyproject.toml +1 -1
  4. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/commands/sync.py +37 -2
  5. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-arch-core/SKILL.md +3 -1
  6. yjcli-0.2.0/src/yjcli/data/skills/yj-scheduler/SKILL.md +124 -0
  7. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/AGENTS.md +1 -0
  8. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/modules/constants.py +2 -0
  9. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/services/scaffold.py +1 -1
  10. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/services/sync.py +2 -14
  11. {yjcli-0.1.3 → yjcli-0.2.0}/.gitignore +0 -0
  12. {yjcli-0.1.3 → yjcli-0.2.0}/LICENSE +0 -0
  13. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/__init__.py +0 -0
  14. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/__main__.py +0 -0
  15. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/cli.py +0 -0
  16. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/commands/__init__.py +0 -0
  17. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/commands/init_cmd.py +0 -0
  18. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/commands/platform.py +0 -0
  19. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/commands/service.py +0 -0
  20. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/__init__.py +0 -0
  21. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-backend-msa/SKILL.md +0 -0
  22. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-backend-service/SKILL.md +0 -0
  23. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-browser-extension/SKILL.md +0 -0
  24. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-cli/SKILL.md +0 -0
  25. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-frontend/SKILL.md +0 -0
  26. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-mobile-app/SKILL.md +0 -0
  27. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/skills/yj-pc-app/SKILL.md +0 -0
  28. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/.gitignore +0 -0
  29. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/Makefile +0 -0
  30. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/TOOLS.md +0 -0
  31. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/make.bat +0 -0
  32. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.development +0 -0
  33. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.examples +0 -0
  34. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.local-dev +0 -0
  35. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.production +0 -0
  36. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.development +0 -0
  37. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.examples +0 -0
  38. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.local-dev +0 -0
  39. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.production +0 -0
  40. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.development +0 -0
  41. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.examples +0 -0
  42. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.local-dev +0 -0
  43. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.production +0 -0
  44. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/frontend/package.json +0 -0
  45. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/frontend/vite.config.ts +0 -0
  46. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/scripts/run.bat +0 -0
  47. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/platform/scripts/run.sh +0 -0
  48. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/data/templates/settings.json +0 -0
  49. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/modules/__init__.py +0 -0
  50. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/modules/fsutil.py +0 -0
  51. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/modules/paths.py +0 -0
  52. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/modules/prompt.py +0 -0
  53. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/services/__init__.py +0 -0
  54. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/services/status.py +0 -0
  55. {yjcli-0.1.3 → yjcli-0.2.0}/src/yjcli/services/wiring.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yjcli
3
- Version: 0.1.3
3
+ Version: 0.2.0
4
4
  Summary: Scaffold platforms, services, and AI agent wiring (Cursor/Claude/Codex) for YJ architecture repos.
5
5
  Project-URL: Homepage, https://github.com/yseiren87/yjcli
6
6
  Project-URL: Repository, https://github.com/yseiren87/yjcli
@@ -68,7 +68,7 @@ make backend NAME=api # start one service
68
68
 
69
69
  Use with `-t` / `--type` (repeatable on `init` / `platform add`):
70
70
 
71
- `backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension`
71
+ `backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension` · `scheduler`
72
72
 
73
73
  ## What `init` creates
74
74
 
@@ -129,10 +129,11 @@ Edit `AGENTS.md` only; do not edit `CLAUDE.md` by hand. Use `migrate` when upgra
129
129
 
130
130
  - `platform add` only creates platform roots (no services, no skills/Makefile — use `service add` / `sync`).
131
131
  - `service add` needs the platform root first (`init` or `platform add`).
132
- - Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed.
132
+ - Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed, and pass
133
+ `--yes` for every `sync` command.
133
134
  - `doctor` checks the **installed package** assets, not your target repo.
134
135
  - `sync skills` / `sync all` remove legacy `.cursor/rules` and `.claude/rules` if present.
135
- - `sync migrate` also overwrites `AGENTS.md` from the package (destructive); requires `--yes` when non-interactive.
136
+ - `sync migrate` also overwrites `AGENTS.md` from the package (destructive).
136
137
 
137
138
  ## Commands
138
139
 
@@ -145,9 +146,11 @@ yjcli init --force
145
146
  yjcli platform add
146
147
  yjcli platform add --all
147
148
  yjcli platform add -t cli
149
+ yjcli platform add -t scheduler
148
150
 
149
151
  yjcli service add
150
152
  yjcli service add -p backend -n api
153
+ yjcli service add -p scheduler -n operations
151
154
 
152
155
  yjcli sync agents
153
156
  yjcli sync skills
@@ -43,7 +43,7 @@ make backend NAME=api # start one service
43
43
 
44
44
  Use with `-t` / `--type` (repeatable on `init` / `platform add`):
45
45
 
46
- `backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension`
46
+ `backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension` · `scheduler`
47
47
 
48
48
  ## What `init` creates
49
49
 
@@ -104,10 +104,11 @@ Edit `AGENTS.md` only; do not edit `CLAUDE.md` by hand. Use `migrate` when upgra
104
104
 
105
105
  - `platform add` only creates platform roots (no services, no skills/Makefile — use `service add` / `sync`).
106
106
  - `service add` needs the platform root first (`init` or `platform add`).
107
- - Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed.
107
+ - Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed, and pass
108
+ `--yes` for every `sync` command.
108
109
  - `doctor` checks the **installed package** assets, not your target repo.
109
110
  - `sync skills` / `sync all` remove legacy `.cursor/rules` and `.claude/rules` if present.
110
- - `sync migrate` also overwrites `AGENTS.md` from the package (destructive); requires `--yes` when non-interactive.
111
+ - `sync migrate` also overwrites `AGENTS.md` from the package (destructive).
111
112
 
112
113
  ## Commands
113
114
 
@@ -120,9 +121,11 @@ yjcli init --force
120
121
  yjcli platform add
121
122
  yjcli platform add --all
122
123
  yjcli platform add -t cli
124
+ yjcli platform add -t scheduler
123
125
 
124
126
  yjcli service add
125
127
  yjcli service add -p backend -n api
128
+ yjcli service add -p scheduler -n operations
126
129
 
127
130
  yjcli sync agents
128
131
  yjcli sync skills
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "yjcli"
3
- version = "0.1.3"
3
+ version = "0.2.0"
4
4
  description = "Scaffold platforms, services, and AI agent wiring (Cursor/Claude/Codex) for YJ architecture repos."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -6,6 +6,7 @@ from pathlib import Path
6
6
 
7
7
  import typer
8
8
 
9
+ from yjcli.modules.prompt import abort
9
10
  from yjcli.services import sync as sync_svc
10
11
 
11
12
  app = typer.Typer(
@@ -18,6 +19,26 @@ app = typer.Typer(
18
19
  )
19
20
 
20
21
 
22
+ def _confirm_sync(*, yes: bool, target: str) -> bool:
23
+ if yes:
24
+ return True
25
+ while True:
26
+ try:
27
+ answer = typer.prompt(
28
+ f"{target} files will be overwritten. Continue? [y/n]",
29
+ default=None,
30
+ show_default=False,
31
+ ).strip().lower()
32
+ except (EOFError, typer.Abort):
33
+ abort("non-interactive stdin; pass --yes")
34
+ if answer == "y":
35
+ return True
36
+ if answer == "n":
37
+ typer.echo("sync cancelled.")
38
+ return False
39
+ typer.echo("Enter y or n.", err=True)
40
+
41
+
21
42
  @app.command("agents")
22
43
  def sync_agents(
23
44
  path: Path = typer.Option(
@@ -28,8 +49,11 @@ def sync_agents(
28
49
  dir_okay=True,
29
50
  resolve_path=True,
30
51
  ),
52
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation."),
31
53
  ) -> None:
32
54
  """Overwrite CLAUDE.md from AGENTS.md (edit AGENTS.md only)."""
55
+ if not _confirm_sync(yes=yes, target="Agent mirror"):
56
+ return
33
57
  sync_svc.sync_agents(path)
34
58
 
35
59
 
@@ -43,8 +67,11 @@ def sync_skills(
43
67
  dir_okay=True,
44
68
  resolve_path=True,
45
69
  ),
70
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation."),
46
71
  ) -> None:
47
72
  """Overwrite .cursor/.claude/.agents skills from the yjcli package."""
73
+ if not _confirm_sync(yes=yes, target="Skill"):
74
+ return
48
75
  sync_svc.sync_skills(path, force=True)
49
76
 
50
77
 
@@ -58,8 +85,11 @@ def sync_make(
58
85
  dir_okay=True,
59
86
  resolve_path=True,
60
87
  ),
88
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation."),
61
89
  ) -> None:
62
90
  """Overwrite root Makefile/make.bat and installed platforms' run.sh/run.bat."""
91
+ if not _confirm_sync(yes=yes, target="Make and run script"):
92
+ return
63
93
  sync_svc.sync_make(path, force=True)
64
94
 
65
95
 
@@ -73,11 +103,14 @@ def sync_all(
73
103
  dir_okay=True,
74
104
  resolve_path=True,
75
105
  ),
106
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation."),
76
107
  ) -> None:
77
108
  """Sync AGENTS.md → CLAUDE.md, skills, make files, and platform run scripts.
78
109
 
79
110
  Does not overwrite AGENTS.md from the package (use `sync migrate` for that).
80
111
  """
112
+ if not _confirm_sync(yes=yes, target="Agent mirror, skill, make, and run script"):
113
+ return
81
114
  sync_svc.sync_all(path, force=True)
82
115
 
83
116
 
@@ -95,7 +128,7 @@ def sync_migrate(
95
128
  False,
96
129
  "--yes",
97
130
  "-y",
98
- help="Skip confirmation (required when stdin is not a TTY).",
131
+ help="Skip confirmation.",
99
132
  ),
100
133
  ) -> None:
101
134
  """Force-replace agent wiring from the package (destructive upgrade).
@@ -104,4 +137,6 @@ def sync_migrate(
104
137
  Makefile/make.bat, platform run scripts, TOOLS.md, .gitignore,
105
138
  .claude/settings.json. Removes legacy .cursor/rules, .claude/rules, .agent.
106
139
  """
107
- sync_svc.sync_migrate(path, yes=yes)
140
+ if not _confirm_sync(yes=yes, target="Agent wiring and root template"):
141
+ return
142
+ sync_svc.sync_migrate(path)
@@ -30,6 +30,7 @@ mobile-app/ # yj-mobile-app
30
30
  pc-app/ # yj-pc-app
31
31
  cli/ # yj-cli
32
32
  browser-extension/ # yj-browser-extension
33
+ scheduler/ # yj-scheduler
33
34
  ```
34
35
 
35
36
  ```text
@@ -64,7 +65,7 @@ Required files at each service root (no plain `.env`):
64
65
  `.env.local` convention unless a thin loader maps it to this structure.
65
66
  - Env field sets come from `templates/platform/envs/<kind>/` via platform mapping (`listen` / `worker` / `app`).
66
67
  - `listen`: `backend` (PORT 8080), `frontend` (PORT 5173)
67
- - `worker`: `backend-service`, `browser-extension/native_*` (HOST/PORT optional)
68
+ - `worker`: `backend-service`, `browser-extension/native_*`, `scheduler` (HOST/PORT optional)
68
69
  - `app`: `cli`, `mobile-app`, `pc-app`, `browser-extension` (NAME/VERSION only)
69
70
  Do not invent fields outside those templates; environment filenames remain
70
71
  extensible through the `.env.<environment>` pattern above.
@@ -93,6 +94,7 @@ Required files at each service root (no plain `.env`):
93
94
  | `cli/**` | `yj-cli` |
94
95
  | `browser-extension/native_*/**` | `yj-backend-service` |
95
96
  | `browser-extension/**` (other) | `yj-browser-extension` |
97
+ | `scheduler/**` | `yj-scheduler` |
96
98
 
97
99
  Never load all platform skills. Never apply a platform skill outside its folder.
98
100
 
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: yj-scheduler
3
+ description: >-
4
+ Long-running scheduler architecture for multiple periodic batch jobs. Use
5
+ only when editing scheduler/**. Language-agnostic: use an established
6
+ scheduling framework from the project's ecosystem without prescribing a
7
+ specific library. Covers job registration, execution isolation, overlap,
8
+ misfires, timezones, retries, locks, observability, and graceful shutdown.
9
+ Do not use for backend/, backend-service/, frontend/, mobile-app/, pc-app/,
10
+ cli/, or browser-extension/.
11
+ ---
12
+
13
+ # yj-scheduler
14
+
15
+ Requires `yj-arch-core`. Scope: **`scheduler/` only**.
16
+
17
+ ## Purpose
18
+
19
+ Run multiple recurring batch jobs in one or more long-running scheduler
20
+ processes. Use an established scheduling framework from the selected language
21
+ ecosystem. Choose the concrete framework from the repository's stack and
22
+ existing dependencies.
23
+
24
+ Do not implement cron parsing, durable scheduling, misfire handling, or a
25
+ `while` + `sleep` scheduling loop from scratch.
26
+
27
+ ## Shape
28
+
29
+ ```text
30
+ scheduler/
31
+ scripts/ # platform-level only
32
+ {scheduler_name}/ # one deployable scheduler process
33
+ apps/ # entry: boot, registration, wiring, shutdown
34
+ services/
35
+ {job_name}/ # one batch workflow
36
+ domains/ # optional: owned concepts only
37
+ modules/ # scheduler adapter, db/api clients, lock, clock
38
+ ```
39
+
40
+ - One scheduler process may register multiple related jobs.
41
+ - Split jobs into separate `{scheduler_name}` deployables only when they need
42
+ independent deployment, scaling, dependencies, permissions, or failure isolation.
43
+ - Do not add per-job `scripts/` or Makefiles. Root `make scheduler` runs all
44
+ scheduler services; `NAME=<scheduler_name>` runs one.
45
+ - This is a long-running worker platform. `HOST` and `PORT` are optional and
46
+ should exist only when the process exposes a real endpoint.
47
+
48
+ ## Roles
49
+
50
+ ### entry (`apps`)
51
+
52
+ - Create and configure the scheduling framework, register triggers, wire job
53
+ handlers, start the process, and perform graceful shutdown.
54
+ - Keep registration declarative and discoverable in one entry area.
55
+ - Framework callbacks must be thin: add execution context, call one flow, and
56
+ report its result. No query, transformation, or persistence logic in callbacks.
57
+
58
+ ### flow (`services/{job_name}`)
59
+
60
+ - Each periodic job is an independently testable workflow.
61
+ - Own job-specific input, orchestration, batching, checkpointing, and result shape.
62
+ - A failure in one job must not terminate or block unrelated jobs.
63
+ - Make operations idempotent whenever a retry or duplicate trigger is possible.
64
+
65
+ ### domain / infra
66
+
67
+ - Add `domains/` only for concepts or shared policy owned by this process;
68
+ persistence is not required. Do not create a domain merely because a job exists.
69
+ - Put framework integration, distributed locks, clocks, persistence, logging,
70
+ and external clients in `modules/`.
71
+ - Do not import another platform's source tree; communicate through explicit
72
+ APIs or generated contracts.
73
+
74
+ ## Scheduling policy
75
+
76
+ For every job, make these decisions explicit near its registration or config:
77
+
78
+ - stable job identifier and handler
79
+ - periodic or calendar trigger and explicit timezone
80
+ - whether overlapping executions are allowed
81
+ - misfire behavior (skip, coalesce, or catch up)
82
+ - timeout, retry, and backoff behavior
83
+ - concurrency limit and multi-instance ownership/locking strategy
84
+
85
+ Never rely implicitly on the host's local timezone. Do not scatter schedule
86
+ expressions across callbacks. Fixed business schedules may live in typed code or
87
+ project configuration; expose them as environment-specific settings only when
88
+ deployments genuinely need different schedules.
89
+
90
+ When more than one scheduler instance can run, use the framework's persistent
91
+ job store/single-run facility or a distributed lock. A process-local mutex does
92
+ not prevent duplicate execution across instances.
93
+
94
+ ## Reliability and observability
95
+
96
+ - Log job id, execution/run id, scheduled time, actual start, completion or
97
+ failure, duration, and retry attempt using structured fields.
98
+ - Define shutdown behavior: stop accepting triggers, then finish or safely
99
+ cancel active jobs within a bounded grace period.
100
+ - Long-running or high-volume jobs should use bounded batches and checkpoints so
101
+ they can resume safely after interruption.
102
+ - Keep retry scope narrow. Do not retry permanent validation or authorization
103
+ failures as though they were transient infrastructure failures.
104
+ - Inject or wrap the clock in flow/domain tests; do not make business rules
105
+ depend directly on wall-clock calls throughout the codebase.
106
+
107
+ ## Import direction
108
+
109
+ ```text
110
+ entry/framework callback -> flow -> domain? -> infra
111
+ entry -> infra
112
+ flow -> infra
113
+ ```
114
+
115
+ Forbidden: business logic in trigger callbacks; flow importing entry/framework
116
+ bootstrap; domain importing scheduler framework types; jobs calling one another
117
+ for sequencing when a single coordinating flow owns the workflow.
118
+
119
+ ## Editing scope
120
+
121
+ - Stay within `scheduler/{scheduler_name}/` unless the task explicitly changes
122
+ shared contracts or platform wiring.
123
+ - Prefer extending an existing scheduler process for related jobs; do not create
124
+ one deployable per cron expression automatically.
@@ -29,6 +29,7 @@ When creating, modifying, reviewing, or refactoring code:
29
29
  | `cli/**` | `yj-cli` |
30
30
  | `browser-extension/native_*/**` | `yj-backend-service` |
31
31
  | `browser-extension/**` (other) | `yj-browser-extension` |
32
+ | `scheduler/**` | `yj-scheduler` |
32
33
 
33
34
  Never load all platform skills. Never apply a platform skill outside its folder.
34
35
 
@@ -10,6 +10,7 @@ PLATFORMS: tuple[str, ...] = (
10
10
  "pc-app",
11
11
  "cli",
12
12
  "browser-extension",
13
+ "scheduler",
13
14
  )
14
15
 
15
16
  RESERVED_SERVICE_NAMES: frozenset[str] = frozenset({"scripts", "proto"})
@@ -26,4 +27,5 @@ PLATFORM_ENV: dict[str, tuple[str, dict[str, str]]] = {
26
27
  "mobile-app": ("app", {}),
27
28
  "pc-app": ("app", {}),
28
29
  "browser-extension": ("app", {}),
30
+ "scheduler": ("worker", {}),
29
31
  }
@@ -122,7 +122,7 @@ def create_service(root: Path, platform: str, name: str) -> None:
122
122
  _copy_env_templates(platform, name, base)
123
123
  _copy_platform_extras(platform, name, base)
124
124
 
125
- if platform in {"backend", "backend-service"}:
125
+ if platform in {"backend", "backend-service", "scheduler"}:
126
126
  for sub in ("apps", "services", "domains", "modules"):
127
127
  (base / sub).mkdir(exist_ok=True)
128
128
  elif platform == "frontend":
@@ -9,7 +9,7 @@ import typer
9
9
 
10
10
  from yjcli.modules import paths
11
11
  from yjcli.modules.constants import PLATFORMS
12
- from yjcli.modules.fsutil import copy_file, copy_tree, ensure_real_dir, is_interactive
12
+ from yjcli.modules.fsutil import copy_file, copy_tree, ensure_real_dir
13
13
  from yjcli.modules.prompt import abort
14
14
 
15
15
  _SKILL_DEST_RELS = (
@@ -114,25 +114,13 @@ def sync_all(root: Path, *, force: bool = True) -> None:
114
114
  sync_make(root, force=force)
115
115
 
116
116
 
117
- def sync_migrate(root: Path, *, yes: bool = False) -> None:
117
+ def sync_migrate(root: Path) -> None:
118
118
  """Force-replace agent wiring + root templates from the package (destructive).
119
119
 
120
120
  Unlike `sync all`, this overwrites `AGENTS.md` from the package template,
121
121
  wipes skill directories (drops stale skills), removes legacy rules / `.agent`,
122
122
  and refreshes Claude settings + TOOLS.md / .gitignore / make scripts.
123
123
  """
124
- if not yes:
125
- if not is_interactive():
126
- abort("migrate requires --yes in non-interactive mode")
127
- answer = typer.prompt(
128
- "migrate overwrites AGENTS.md, skills, Makefile, TOOLS.md, "
129
- ".gitignore, .claude/settings.json; removes legacy rules/.agent. "
130
- "Continue? [y/N]",
131
- default="N",
132
- )
133
- if answer.strip().lower() not in {"y", "yes"}:
134
- abort("migrate cancelled")
135
-
136
124
  typer.echo("== migrate: strip legacy ==")
137
125
  _remove_legacy_rules_dirs(root)
138
126
  _remove_path(root, Path(".agent"), label="legacy")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes