yjcli 0.1.4__tar.gz → 0.2.1__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 (63) hide show
  1. {yjcli-0.1.4 → yjcli-0.2.1}/PKG-INFO +18 -11
  2. {yjcli-0.1.4 → yjcli-0.2.1}/README.md +17 -10
  3. {yjcli-0.1.4 → yjcli-0.2.1}/pyproject.toml +1 -1
  4. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-arch-core/SKILL.md +15 -6
  5. yjcli-0.2.1/src/yjcli/data/skills/yj-scheduler/SKILL.md +124 -0
  6. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/AGENTS.md +14 -1
  7. yjcli-0.2.1/src/yjcli/data/templates/Diff.md +9 -0
  8. yjcli-0.2.1/src/yjcli/data/templates/Makefile +47 -0
  9. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/make.bat +23 -3
  10. yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-common.bat +33 -0
  11. yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-common.sh +35 -0
  12. yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-development.bat +21 -0
  13. yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-development.sh +20 -0
  14. yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-production.bat +21 -0
  15. yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-production.sh +20 -0
  16. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/constants.py +2 -0
  17. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/scaffold.py +29 -9
  18. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/sync.py +33 -12
  19. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/wiring.py +7 -1
  20. yjcli-0.1.4/src/yjcli/data/templates/Makefile +0 -34
  21. {yjcli-0.1.4 → yjcli-0.2.1}/.gitignore +0 -0
  22. {yjcli-0.1.4 → yjcli-0.2.1}/LICENSE +0 -0
  23. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/__init__.py +0 -0
  24. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/__main__.py +0 -0
  25. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/cli.py +0 -0
  26. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/__init__.py +0 -0
  27. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/init_cmd.py +0 -0
  28. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/platform.py +0 -0
  29. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/service.py +0 -0
  30. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/sync.py +0 -0
  31. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/__init__.py +0 -0
  32. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-backend-msa/SKILL.md +0 -0
  33. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-backend-service/SKILL.md +0 -0
  34. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-browser-extension/SKILL.md +0 -0
  35. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-cli/SKILL.md +0 -0
  36. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-frontend/SKILL.md +0 -0
  37. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-mobile-app/SKILL.md +0 -0
  38. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-pc-app/SKILL.md +0 -0
  39. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/.gitignore +0 -0
  40. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/TOOLS.md +0 -0
  41. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.development +0 -0
  42. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.examples +0 -0
  43. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.local-dev +0 -0
  44. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.production +0 -0
  45. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.development +0 -0
  46. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.examples +0 -0
  47. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.local-dev +0 -0
  48. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.production +0 -0
  49. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.development +0 -0
  50. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.examples +0 -0
  51. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.local-dev +0 -0
  52. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.production +0 -0
  53. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/frontend/package.json +0 -0
  54. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/frontend/vite.config.ts +0 -0
  55. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/scripts/run.bat +0 -0
  56. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/scripts/run.sh +0 -0
  57. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/settings.json +0 -0
  58. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/__init__.py +0 -0
  59. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/fsutil.py +0 -0
  60. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/paths.py +0 -0
  61. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/prompt.py +0 -0
  62. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/__init__.py +0 -0
  63. {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/status.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yjcli
3
- Version: 0.1.4
3
+ Version: 0.2.1
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
 
@@ -76,14 +76,17 @@ Use with `-t` / `--type` (repeatable on `init` / `platform add`):
76
76
  - Skills under `.cursor/skills/`, `.claude/skills/`, `.agents/skills/` (Codex)
77
77
  - Claude `settings.json`
78
78
  - Root `Makefile`, `make.bat`, `TOOLS.md`, `.gitignore`
79
- - Selected platform roots (`*/scripts/run.sh` / `run.bat`)
79
+ - `Diff.md` — user-maintained architecture difference and manual restoration notes
80
+ - Selected platform roots with `scripts/run.*` and development/production deploy templates
80
81
 
81
- The root `Makefile` / `make.bat` is the repository-owned extension point for
82
- project automation. Projects may add commands such as `<platform>-build` or
83
- `<platform>-deploy` and reuse optional `NAME=<service>` selection. Defining and
84
- implementing init/install/build/deploy behavior is the project's responsibility;
85
- yjcli does not generate action scripts. Do not add per-service `scripts/`
86
- directories or per-service Makefiles.
82
+ The root `Makefile` / `make.bat` wires platform run and deploy entry points. Deploy
83
+ templates print the exact file to implement and fail until the project supplies
84
+ its build/package and upload logic. They remain platform-level; do not add
85
+ per-service `scripts/` directories or per-service Makefiles.
86
+
87
+ `Diff.md` is created only when missing, including with `init --force`. yjcli never
88
+ reads, updates, overwrites, or uses it for automatic restoration during sync or
89
+ migration.
87
90
 
88
91
  Operating rules (skill routing, output discipline) are in `AGENTS.md` — not in
89
92
  `.cursor/rules` / `.claude/rules`.
@@ -102,6 +105,8 @@ inferring npm, uv, Go, or another language/runtime from project manifests.
102
105
  ```bash
103
106
  make <platform> # all services under that platform (concurrent)
104
107
  make <platform> NAME=<service> # one service
108
+ make <platform>-deploy-development [NAME=<service>]
109
+ make <platform>-deploy-production [NAME=<service>]
105
110
  make help
106
111
  ```
107
112
 
@@ -111,7 +116,7 @@ make help
111
116
  |---------|------|
112
117
  | `yjcli sync agents` | After editing `AGENTS.md` — refreshes `CLAUDE.md` |
113
118
  | `yjcli sync skills` | Refresh packaged skills (Cursor / Claude / Codex) |
114
- | `yjcli sync make` | Overwrite root `Makefile` / `make.bat` and each installed platform’s `scripts/run.sh` · `run.bat` |
119
+ | `yjcli sync make` | Overwrite root make/run files; install missing deploy scripts while preserving implemented ones |
115
120
  | `yjcli sync all` | Soft upgrade — mirror CLAUDE + skills + make (**keeps** your `AGENTS.md`) |
116
121
  | `yjcli sync migrate -y` | **Hard** upgrade — package template overwrites `AGENTS.md`, wipes skills dirs, drops legacy rules/`.agent`, refreshes settings/TOOLS/gitignore/make |
117
122
 
@@ -127,7 +132,7 @@ Edit `AGENTS.md` only; do not edit `CLAUDE.md` by hand. Use `migrate` when upgra
127
132
 
128
133
  ## Notes
129
134
 
130
- - `platform add` only creates platform roots (no services, no skills/Makefile — use `service add` / `sync`).
135
+ - `platform add` creates platform roots and their run/deploy scripts (no services, skills, or root Makefile).
131
136
  - `service add` needs the platform root first (`init` or `platform add`).
132
137
  - Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed, and pass
133
138
  `--yes` for every `sync` command.
@@ -146,9 +151,11 @@ yjcli init --force
146
151
  yjcli platform add
147
152
  yjcli platform add --all
148
153
  yjcli platform add -t cli
154
+ yjcli platform add -t scheduler
149
155
 
150
156
  yjcli service add
151
157
  yjcli service add -p backend -n api
158
+ yjcli service add -p scheduler -n operations
152
159
 
153
160
  yjcli sync agents
154
161
  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
 
@@ -51,14 +51,17 @@ Use with `-t` / `--type` (repeatable on `init` / `platform add`):
51
51
  - Skills under `.cursor/skills/`, `.claude/skills/`, `.agents/skills/` (Codex)
52
52
  - Claude `settings.json`
53
53
  - Root `Makefile`, `make.bat`, `TOOLS.md`, `.gitignore`
54
- - Selected platform roots (`*/scripts/run.sh` / `run.bat`)
54
+ - `Diff.md` — user-maintained architecture difference and manual restoration notes
55
+ - Selected platform roots with `scripts/run.*` and development/production deploy templates
55
56
 
56
- The root `Makefile` / `make.bat` is the repository-owned extension point for
57
- project automation. Projects may add commands such as `<platform>-build` or
58
- `<platform>-deploy` and reuse optional `NAME=<service>` selection. Defining and
59
- implementing init/install/build/deploy behavior is the project's responsibility;
60
- yjcli does not generate action scripts. Do not add per-service `scripts/`
61
- directories or per-service Makefiles.
57
+ The root `Makefile` / `make.bat` wires platform run and deploy entry points. Deploy
58
+ templates print the exact file to implement and fail until the project supplies
59
+ its build/package and upload logic. They remain platform-level; do not add
60
+ per-service `scripts/` directories or per-service Makefiles.
61
+
62
+ `Diff.md` is created only when missing, including with `init --force`. yjcli never
63
+ reads, updates, overwrites, or uses it for automatic restoration during sync or
64
+ migration.
62
65
 
63
66
  Operating rules (skill routing, output discipline) are in `AGENTS.md` — not in
64
67
  `.cursor/rules` / `.claude/rules`.
@@ -77,6 +80,8 @@ inferring npm, uv, Go, or another language/runtime from project manifests.
77
80
  ```bash
78
81
  make <platform> # all services under that platform (concurrent)
79
82
  make <platform> NAME=<service> # one service
83
+ make <platform>-deploy-development [NAME=<service>]
84
+ make <platform>-deploy-production [NAME=<service>]
80
85
  make help
81
86
  ```
82
87
 
@@ -86,7 +91,7 @@ make help
86
91
  |---------|------|
87
92
  | `yjcli sync agents` | After editing `AGENTS.md` — refreshes `CLAUDE.md` |
88
93
  | `yjcli sync skills` | Refresh packaged skills (Cursor / Claude / Codex) |
89
- | `yjcli sync make` | Overwrite root `Makefile` / `make.bat` and each installed platform’s `scripts/run.sh` · `run.bat` |
94
+ | `yjcli sync make` | Overwrite root make/run files; install missing deploy scripts while preserving implemented ones |
90
95
  | `yjcli sync all` | Soft upgrade — mirror CLAUDE + skills + make (**keeps** your `AGENTS.md`) |
91
96
  | `yjcli sync migrate -y` | **Hard** upgrade — package template overwrites `AGENTS.md`, wipes skills dirs, drops legacy rules/`.agent`, refreshes settings/TOOLS/gitignore/make |
92
97
 
@@ -102,7 +107,7 @@ Edit `AGENTS.md` only; do not edit `CLAUDE.md` by hand. Use `migrate` when upgra
102
107
 
103
108
  ## Notes
104
109
 
105
- - `platform add` only creates platform roots (no services, no skills/Makefile — use `service add` / `sync`).
110
+ - `platform add` creates platform roots and their run/deploy scripts (no services, skills, or root Makefile).
106
111
  - `service add` needs the platform root first (`init` or `platform add`).
107
112
  - Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed, and pass
108
113
  `--yes` for every `sync` command.
@@ -121,9 +126,11 @@ yjcli init --force
121
126
  yjcli platform add
122
127
  yjcli platform add --all
123
128
  yjcli platform add -t cli
129
+ yjcli platform add -t scheduler
124
130
 
125
131
  yjcli service add
126
132
  yjcli service add -p backend -n api
133
+ yjcli service add -p scheduler -n operations
127
134
 
128
135
  yjcli sync agents
129
136
  yjcli sync skills
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "yjcli"
3
- version = "0.1.4"
3
+ version = "0.2.1"
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"
@@ -30,11 +30,12 @@ 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
36
37
  {platform}/
37
- scripts/ # platform-level only
38
+ scripts/ # platform run + deploy entry points
38
39
  {service_name}/ # one deployable / one app
39
40
  ```
40
41
 
@@ -45,10 +46,17 @@ browser-extension/ # yj-browser-extension
45
46
  `install`, or `help` targets. Do not add per-service `scripts/`.
46
47
  Root `make <platform>` starts all services under that platform (concurrent); `NAME=<service>` runs one.
47
48
  Platforms run via `*/scripts/run.*`; services are sibling dirs created with `yjcli service add`.
48
- - The root `Makefile` / `make.bat` is repository-owned and may be extended. Prefer
49
- `<platform>-<action> [NAME=<service>]` when an action should target all services
50
- or one service (for example, `backend-deploy`). The repository owns and implements
51
- actions such as init/install/build/deploy; yjcli does not generate action scripts.
49
+ - The root `Makefile` / `make.bat` wires platform run and deploy commands. Use
50
+ `<platform>-deploy-development|production [NAME=<service>]` for deploys.
51
+ `deploy-common.*` owns shared build/package preparation; the environment-specific
52
+ deploy script calls it and then owns upload/rollout. Generated deploy scripts fail
53
+ with an implementation prompt until the repository replaces their guarded stubs.
54
+ - Deploy scripts are repository-owned after creation. `yjcli sync make` installs
55
+ missing deploy scripts but preserves existing ones.
56
+ - `Diff.md` is an optional, user-maintained reference for meaningful architecture
57
+ differences from yjcli defaults and their manual restoration notes. Update it
58
+ when that record would help, but never treat it as an automated sync, migration,
59
+ backup, comparison, or restoration mechanism. Never place secrets in it.
52
60
 
53
61
 
54
62
  ## Environment (guardrails only)
@@ -64,7 +72,7 @@ Required files at each service root (no plain `.env`):
64
72
  `.env.local` convention unless a thin loader maps it to this structure.
65
73
  - Env field sets come from `templates/platform/envs/<kind>/` via platform mapping (`listen` / `worker` / `app`).
66
74
  - `listen`: `backend` (PORT 8080), `frontend` (PORT 5173)
67
- - `worker`: `backend-service`, `browser-extension/native_*` (HOST/PORT optional)
75
+ - `worker`: `backend-service`, `browser-extension/native_*`, `scheduler` (HOST/PORT optional)
68
76
  - `app`: `cli`, `mobile-app`, `pc-app`, `browser-extension` (NAME/VERSION only)
69
77
  Do not invent fields outside those templates; environment filenames remain
70
78
  extensible through the `.env.<environment>` pattern above.
@@ -93,6 +101,7 @@ Required files at each service root (no plain `.env`):
93
101
  | `cli/**` | `yj-cli` |
94
102
  | `browser-extension/native_*/**` | `yj-backend-service` |
95
103
  | `browser-extension/**` (other) | `yj-browser-extension` |
104
+ | `scheduler/**` | `yj-scheduler` |
96
105
 
97
106
  Never load all platform skills. Never apply a platform skill outside its folder.
98
107
 
@@ -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
 
@@ -57,8 +58,12 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
57
58
  | `AGENTS.md` | Agent / contributor guide (this file) — source of truth |
58
59
  | `CLAUDE.md` | Mirror of `AGENTS.md` — do not edit; refresh with `yjcli sync agents` |
59
60
  | `TOOLS.md` | Release-tools feature spec (version / deploy / git) |
60
- | `Makefile` | Extensible root entry — `make <platform>` (all services) or `NAME=<service>` (one); repository may add `<platform>-<action>` targets |
61
+ | `Diff.md` | User-maintained reference for project differences from yjcli defaults; yjcli never updates or restores from it |
62
+ | `Makefile` | Root entry — run via `make <platform>`; deploy via `<platform>-deploy-development\|production`, optionally with `NAME=<service>` |
61
63
  | `make.bat` | Extensible Windows counterpart of root Makefile |
64
+ | `<platform>/scripts/deploy-common.*` | Repository-owned shared build/package implementation |
65
+ | `<platform>/scripts/deploy-development.*` | Repository-owned development upload/deploy implementation |
66
+ | `<platform>/scripts/deploy-production.*` | Repository-owned production upload/deploy implementation |
62
67
  | `.gitignore` | Canonical ignore rules |
63
68
  | `.cursor/skills/` | Cursor skills (copied from package) |
64
69
  | `.claude/skills/` | Claude skills (copied from package) |
@@ -93,6 +98,10 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
93
98
 
94
99
  # build
95
100
  <command>
101
+
102
+ # deploy (generated stubs fail until implemented)
103
+ make <platform>-deploy-development [NAME=<service>]
104
+ make <platform>-deploy-production [NAME=<service>]
96
105
  ```
97
106
 
98
107
  ---
@@ -129,10 +138,13 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
129
138
  ### Do
130
139
 
131
140
  - `<item>`
141
+ - Record meaningful architecture differences from yjcli defaults in `Diff.md` when useful for manual restoration.
132
142
 
133
143
  ### Don't
134
144
 
135
145
  - `<item>`
146
+ - Do not expect `Diff.md` to drive sync, migration, comparison, backup, or automatic restoration.
147
+ - Do not put secrets in `Diff.md`.
136
148
 
137
149
  ---
138
150
 
@@ -157,5 +169,6 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
157
169
  | Kind | Location |
158
170
  |------|----------|
159
171
  | Release tools spec | `TOOLS.md` |
172
+ | Architecture differences | `Diff.md` |
160
173
  | Packaged skills (source) | installed via `yjcli` → `.cursor` / `.claude` / `.agents` skills |
161
174
  | `<kind>` | `<path>` |
@@ -0,0 +1,9 @@
1
+ # 아키텍처 차이점
2
+
3
+ 이 문서는 yjcli가 제공하는 기본 아키텍처와 현재 프로젝트 사이의 차이점을 기록하는 참고 자료다.
4
+
5
+ 템플릿이나 에이전트 연결 파일이 갱신된 뒤 프로젝트 고유의 변경 사항을 사용자가 직접 확인하고 복원할 때 활용한다.
6
+
7
+ yjcli는 이 파일이 없을 때만 최초 생성하며, 이후에는 읽거나 수정하거나 덮어쓰지 않는다. 이 문서의 내용을 이용한 자동 비교, 백업 또는 복원도 수행하지 않는다.
8
+
9
+ 비밀번호, 토큰, 인증정보 등 시크릿은 기록하지 않는다.
@@ -0,0 +1,47 @@
1
+ # Platform targets are discovered from */scripts/run.sh (after yjcli platform add).
2
+ # Usage:
3
+ # make <platform> # all services under that platform (concurrent)
4
+ # make <platform> NAME=<service> # one service
5
+ # Deploy templates are platform-owned extension points. They intentionally fail
6
+ # until the repository implements the printed build/package/upload steps.
7
+
8
+ PLATFORMS := $(patsubst %/scripts/run.sh,%,$(wildcard */scripts/run.sh))
9
+ DEPLOY_DEVELOPMENT_TARGETS := $(addsuffix -deploy-development,$(PLATFORMS))
10
+ DEPLOY_PRODUCTION_TARGETS := $(addsuffix -deploy-production,$(PLATFORMS))
11
+
12
+ .PHONY: help $(PLATFORMS) $(DEPLOY_DEVELOPMENT_TARGETS) $(DEPLOY_PRODUCTION_TARGETS)
13
+
14
+ help:
15
+ @echo "Usage:"
16
+ @echo " make <platform> # start all services concurrently"
17
+ @echo " make <platform> NAME=<service> # start one service"
18
+ @echo " make <platform>-deploy-development [NAME=<service>]"
19
+ @echo " make <platform>-deploy-production [NAME=<service>]"
20
+ @echo ""
21
+ @echo "Available platforms (dirs with scripts/run.sh):"
22
+ @if [ -z "$(PLATFORMS)" ]; then \
23
+ echo " (none — run: yjcli platform add)"; \
24
+ else \
25
+ for p in $(PLATFORMS); do echo " $$p"; done; \
26
+ fi
27
+ @echo ""
28
+ @echo "Example: make backend"
29
+ @echo " make backend NAME=api"
30
+ @echo " make backend-deploy-development NAME=api"
31
+ @echo " make backend-deploy-production NAME=api"
32
+
33
+ $(PLATFORMS):
34
+ @test -x "$@/scripts/run.sh" || (echo "missing: $@/scripts/run.sh"; exit 1)
35
+ @if [ -n "$(NAME)" ]; then \
36
+ "$@/scripts/run.sh" "$(NAME)" $(ARGS); \
37
+ else \
38
+ "$@/scripts/run.sh" $(ARGS); \
39
+ fi
40
+
41
+ $(DEPLOY_DEVELOPMENT_TARGETS): %-deploy-development:
42
+ @test -x "$*/scripts/deploy-development.sh" || (echo "missing: $*/scripts/deploy-development.sh"; exit 1)
43
+ @"$*/scripts/deploy-development.sh" "$(NAME)" $(ARGS)
44
+
45
+ $(DEPLOY_PRODUCTION_TARGETS): %-deploy-production:
46
+ @test -x "$*/scripts/deploy-production.sh" || (echo "missing: $*/scripts/deploy-production.sh"; exit 1)
47
+ @"$*/scripts/deploy-production.sh" "$(NAME)" $(ARGS)
@@ -1,12 +1,24 @@
1
1
  @echo off
2
2
  setlocal EnableExtensions EnableDelayedExpansion
3
- rem Extend this root file with repository-owned platform-action commands as needed,
4
- rem for example: make.bat backend-deploy NAME=api. yjcli does not define them.
3
+ rem Deploy scripts intentionally fail until their printed implementation steps are completed.
5
4
 
6
5
  if /I "%~1"=="" goto help
7
6
  if /I "%~1"=="help" goto help
8
7
 
9
- set "PLATFORM=%~1"
8
+ set "TARGET=%~1"
9
+ set "PLATFORM=%TARGET:-deploy-development=%"
10
+ if /I not "%PLATFORM%"=="%TARGET%" (
11
+ set "DEPLOY_ENV=development"
12
+ goto parse_start
13
+ )
14
+ set "PLATFORM=%TARGET:-deploy-production=%"
15
+ if /I not "%PLATFORM%"=="%TARGET%" (
16
+ set "DEPLOY_ENV=production"
17
+ goto parse_start
18
+ )
19
+ set "PLATFORM=%TARGET%"
20
+
21
+ :parse_start
10
22
  if not exist "%PLATFORM%\scripts\run.bat" (
11
23
  echo Unknown target: %PLATFORM%
12
24
  echo Expected: %PLATFORM%\scripts\run.bat ^(yjcli platform add^)
@@ -23,6 +35,10 @@ shift
23
35
  goto parse
24
36
 
25
37
  :run_exec
38
+ if defined DEPLOY_ENV (
39
+ call "%PLATFORM%\scripts\deploy-%DEPLOY_ENV%.bat" "%NAME%"
40
+ exit /b !ERRORLEVEL!
41
+ )
26
42
  if "%NAME%"=="" (
27
43
  call "%PLATFORM%\scripts\run.bat"
28
44
  ) else (
@@ -34,6 +50,8 @@ exit /b %ERRORLEVEL%
34
50
  echo Usage:
35
51
  echo make.bat ^<platform^> # all services ^(separate windows^)
36
52
  echo make.bat ^<platform^> NAME=^<service^> # one service
53
+ echo make.bat ^<platform^>-deploy-development [NAME=^<service^>]
54
+ echo make.bat ^<platform^>-deploy-production [NAME=^<service^>]
37
55
  echo.
38
56
  echo Available platforms (dirs with scripts\run.bat):
39
57
  set "FOUND="
@@ -47,4 +65,6 @@ if not defined FOUND echo ^(none — run: yjcli platform add^)
47
65
  echo.
48
66
  echo Example: make.bat backend
49
67
  echo make.bat backend NAME=api
68
+ echo make.bat backend-deploy-development NAME=api
69
+ echo make.bat backend-deploy-production NAME=api
50
70
  exit /b 0
@@ -0,0 +1,33 @@
1
+ @echo off
2
+ setlocal EnableExtensions
3
+ rem Shared build/package preparation for development and production deploys.
4
+ rem Replace the implementation guard below with repository-specific commands.
5
+
6
+ set "SCRIPT_DIR=%~dp0"
7
+ for %%D in ("%SCRIPT_DIR%..") do set "PLATFORM_DIR=%%~fD"
8
+ set "ENVIRONMENT=%~1"
9
+ set "NAME=%~2"
10
+
11
+ if /I not "%ENVIRONMENT%"=="development" if /I not "%ENVIRONMENT%"=="production" (
12
+ echo usage: %~nx0 ^<development^|production^> [service] [args...]
13
+ exit /b 1
14
+ )
15
+
16
+ if defined NAME if not exist "%PLATFORM_DIR%\%NAME%\" (
17
+ echo unknown service: %NAME% ^(expected %PLATFORM_DIR%\%NAME%^)
18
+ exit /b 1
19
+ )
20
+
21
+ for %%D in ("%PLATFORM_DIR%") do set "PLATFORM_NAME=%%~nxD"
22
+ echo [deploy] platform: %PLATFORM_NAME%
23
+ echo [deploy] environment: %ENVIRONMENT%
24
+ if defined NAME (echo [deploy] service: %NAME%) else echo [deploy] service: all
25
+ echo deploy common is not implemented.
26
+ echo Implement build/package logic in: %SCRIPT_DIR%deploy-common.bat
27
+ echo Examples: docker build, archive creation, frontend build
28
+
29
+ rem Implementation examples:
30
+ rem docker build -t "example/%NAME%:%ENVIRONMENT%" "%PLATFORM_DIR%"
31
+ rem tar -a -c -f "%NAME%.zip" -C "%PLATFORM_DIR%" "%NAME%"
32
+ rem cd /d "%PLATFORM_DIR%\%NAME%" ^&^& npm ci ^&^& npm run build
33
+ exit /b 1
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Shared build/package preparation for development and production deploys.
3
+ # Replace the implementation guard below with repository-specific commands.
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ PLATFORM_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
8
+ ENVIRONMENT="${1:-}"
9
+ NAME="${2:-}"
10
+
11
+ case "$ENVIRONMENT" in
12
+ development|production) ;;
13
+ *)
14
+ echo "usage: $0 <development|production> [service] [args...]"
15
+ exit 1
16
+ ;;
17
+ esac
18
+
19
+ if [ -n "$NAME" ] && [ ! -d "$PLATFORM_DIR/$NAME" ]; then
20
+ echo "unknown service: $NAME (expected $PLATFORM_DIR/$NAME)"
21
+ exit 1
22
+ fi
23
+
24
+ echo "[deploy] platform: $(basename "$PLATFORM_DIR")"
25
+ echo "[deploy] environment: $ENVIRONMENT"
26
+ echo "[deploy] service: ${NAME:-all}"
27
+ echo "deploy common is not implemented."
28
+ echo "Implement build/package logic in: $SCRIPT_DIR/deploy-common.sh"
29
+ echo "Examples: docker build, archive creation, frontend build"
30
+
31
+ # Implementation examples:
32
+ # docker build -t "example/${NAME:-platform}:$ENVIRONMENT" "$PLATFORM_DIR"
33
+ # tar -czf "${NAME:-platform}.tar.gz" -C "$PLATFORM_DIR" "${NAME:-.}"
34
+ # (cd "$PLATFORM_DIR/$NAME" && npm ci && npm run build)
35
+ exit 1
@@ -0,0 +1,21 @@
1
+ @echo off
2
+ setlocal EnableExtensions
3
+ rem Development deployment entry point. Keep shared preparation in deploy-common.bat.
4
+
5
+ set "SCRIPT_DIR=%~dp0"
6
+ set "NAME=%~1"
7
+ shift
8
+
9
+ call "%SCRIPT_DIR%deploy-common.bat" development "%NAME%" %*
10
+ if errorlevel 1 exit /b %ERRORLEVEL%
11
+
12
+ echo development upload is not implemented.
13
+ echo Implement upload/deploy logic in: %SCRIPT_DIR%deploy-development.bat
14
+ echo Examples: docker push, scp, S3 upload, kubectl apply
15
+
16
+ rem Development upload examples:
17
+ rem docker push "registry.example.com/%NAME%:development"
18
+ rem scp "%ARTIFACT%" "dev-server:/srv/%NAME%/"
19
+ rem aws s3 sync "%DIST_DIR%" "s3://example-development/%NAME%/"
20
+ rem kubectl apply -k deploy/overlays/development
21
+ exit /b 1
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ # Development deployment entry point. Keep shared preparation in deploy-common.sh.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ NAME="${1:-}"
7
+ shift || true
8
+
9
+ "$SCRIPT_DIR/deploy-common.sh" development "$NAME" "$@"
10
+
11
+ echo "development upload is not implemented."
12
+ echo "Implement upload/deploy logic in: $SCRIPT_DIR/deploy-development.sh"
13
+ echo "Examples: docker push, scp, S3 upload, kubectl apply"
14
+
15
+ # Development upload examples:
16
+ # docker push "registry.example.com/$NAME:development"
17
+ # scp "$ARTIFACT" "dev-server:/srv/$NAME/"
18
+ # aws s3 sync "$DIST_DIR" "s3://example-development/$NAME/"
19
+ # kubectl apply -k deploy/overlays/development
20
+ exit 1
@@ -0,0 +1,21 @@
1
+ @echo off
2
+ setlocal EnableExtensions
3
+ rem Production deployment entry point. Keep shared preparation in deploy-common.bat.
4
+
5
+ set "SCRIPT_DIR=%~dp0"
6
+ set "NAME=%~1"
7
+ shift
8
+
9
+ call "%SCRIPT_DIR%deploy-common.bat" production "%NAME%" %*
10
+ if errorlevel 1 exit /b %ERRORLEVEL%
11
+
12
+ echo production upload is not implemented.
13
+ echo Implement upload/deploy logic in: %SCRIPT_DIR%deploy-production.bat
14
+ echo Examples: registry push, production upload, release rollout
15
+
16
+ rem Recommended production steps:
17
+ rem - validate VERSION or release tag
18
+ rem - upload the artifact or push the container image
19
+ rem - deploy to production and run a health check
20
+ rem - roll back on failure
21
+ exit /b 1
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ # Production deployment entry point. Keep shared preparation in deploy-common.sh.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ NAME="${1:-}"
7
+ shift || true
8
+
9
+ "$SCRIPT_DIR/deploy-common.sh" production "$NAME" "$@"
10
+
11
+ echo "production upload is not implemented."
12
+ echo "Implement upload/deploy logic in: $SCRIPT_DIR/deploy-production.sh"
13
+ echo "Examples: registry push, production upload, release rollout"
14
+
15
+ # Recommended production steps:
16
+ # - validate VERSION or release tag
17
+ # - upload the artifact or push the container image
18
+ # - deploy to the production environment and run a health check
19
+ # - roll back on failure
20
+ exit 1
@@ -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
  }
@@ -28,6 +28,17 @@ _DEFAULT_ENV_FILE_NAMES = (
28
28
  ".env.examples",
29
29
  )
30
30
 
31
+ _PLATFORM_SCRIPT_NAMES = (
32
+ "run.sh",
33
+ "run.bat",
34
+ "deploy-common.sh",
35
+ "deploy-common.bat",
36
+ "deploy-development.sh",
37
+ "deploy-development.bat",
38
+ "deploy-production.sh",
39
+ "deploy-production.bat",
40
+ )
41
+
31
42
 
32
43
  def existing_platforms(root: Path) -> list[str]:
33
44
  return [p for p in PLATFORMS if (root / p).is_dir()]
@@ -43,14 +54,21 @@ def create_platform(root: Path, platform: str) -> None:
43
54
  scripts_dir.mkdir(parents=True, exist_ok=True)
44
55
 
45
56
  templates = paths.templates_dir()
46
- run_sh = templates / "platform" / "scripts" / "run.sh"
47
- run_bat = templates / "platform" / "scripts" / "run.bat"
48
- if not run_sh.is_file() or not run_bat.is_file():
49
- abort(f"missing platform scripts under {templates / 'platform' / 'scripts'}")
50
-
51
- shutil.copy2(run_sh, scripts_dir / "run.sh")
52
- shutil.copy2(run_bat, scripts_dir / "run.bat")
53
- (scripts_dir / "run.sh").chmod((scripts_dir / "run.sh").stat().st_mode | 0o111)
57
+ script_templates = templates / "platform" / "scripts"
58
+ missing = [
59
+ name
60
+ for name in _PLATFORM_SCRIPT_NAMES
61
+ if not (script_templates / name).is_file()
62
+ ]
63
+ if missing:
64
+ abort(f"missing platform scripts under {script_templates}: {', '.join(missing)}")
65
+
66
+ for name in _PLATFORM_SCRIPT_NAMES:
67
+ source = script_templates / name
68
+ target = scripts_dir / name
69
+ shutil.copy2(source, target)
70
+ if name.endswith(".sh"):
71
+ target.chmod(target.stat().st_mode | 0o111)
54
72
 
55
73
  if platform == "backend":
56
74
  proto = dest / "proto"
@@ -122,7 +140,7 @@ def create_service(root: Path, platform: str, name: str) -> None:
122
140
  _copy_env_templates(platform, name, base)
123
141
  _copy_platform_extras(platform, name, base)
124
142
 
125
- if platform in {"backend", "backend-service"}:
143
+ if platform in {"backend", "backend-service", "scheduler"}:
126
144
  for sub in ("apps", "services", "domains", "modules"):
127
145
  (base / sub).mkdir(exist_ok=True)
128
146
  elif platform == "frontend":
@@ -242,3 +260,5 @@ def add_service_flow(
242
260
  typer.echo(f"run all: make {chosen}")
243
261
  typer.echo(f"run one: make {chosen} NAME={name}")
244
262
  typer.echo(f" or: {chosen}/scripts/run.sh [{name}]")
263
+ typer.echo(f"deploy development: make {chosen}-deploy-development NAME={name}")
264
+ typer.echo(f"deploy production: make {chosen}-deploy-production NAME={name}")
@@ -76,7 +76,7 @@ def sync_skills(root: Path, *, force: bool = True) -> None:
76
76
 
77
77
 
78
78
  def sync_make(root: Path, *, force: bool = True) -> None:
79
- """Overwrite root Makefile/make.bat and each installed platform's run scripts."""
79
+ """Refresh managed make/run files and install missing deploy templates."""
80
80
  templates = paths.templates_dir()
81
81
  for name in ("Makefile", "make.bat"):
82
82
  src = templates / name
@@ -85,10 +85,23 @@ def sync_make(root: Path, *, force: bool = True) -> None:
85
85
  copy_file(src, root / name, force=force)
86
86
  typer.echo("synced: packaged Makefile, make.bat -> repo root")
87
87
 
88
- run_sh = templates / "platform" / "scripts" / "run.sh"
89
- run_bat = templates / "platform" / "scripts" / "run.bat"
90
- if not run_sh.is_file() or not run_bat.is_file():
91
- abort(f"missing packaged platform scripts under {run_sh.parent}")
88
+ scripts_src = templates / "platform" / "scripts"
89
+ managed_names = ("run.sh", "run.bat")
90
+ deploy_names = (
91
+ "deploy-common.sh",
92
+ "deploy-common.bat",
93
+ "deploy-development.sh",
94
+ "deploy-development.bat",
95
+ "deploy-production.sh",
96
+ "deploy-production.bat",
97
+ )
98
+ missing = [
99
+ name
100
+ for name in (*managed_names, *deploy_names)
101
+ if not (scripts_src / name).is_file()
102
+ ]
103
+ if missing:
104
+ abort(f"missing packaged platform scripts under {scripts_src}: {', '.join(missing)}")
92
105
 
93
106
  installed = [p for p in PLATFORMS if (root / p).is_dir()]
94
107
  if not installed:
@@ -98,13 +111,21 @@ def sync_make(root: Path, *, force: bool = True) -> None:
98
111
  for platform in installed:
99
112
  scripts_dir = root / platform / "scripts"
100
113
  ensure_real_dir(scripts_dir)
101
- dest_sh = scripts_dir / "run.sh"
102
- dest_bat = scripts_dir / "run.bat"
103
- copy_file(run_sh, dest_sh, force=force)
104
- copy_file(run_bat, dest_bat, force=force)
105
- if dest_sh.is_file():
106
- dest_sh.chmod(dest_sh.stat().st_mode | 0o111)
107
- typer.echo(f"synced: {platform}/scripts/run.sh, run.bat")
114
+ for name in managed_names:
115
+ copy_file(scripts_src / name, scripts_dir / name, force=force)
116
+ for name in deploy_names:
117
+ copy_file(scripts_src / name, scripts_dir / name, skip_existing=True)
118
+ executable_names = (
119
+ "run.sh",
120
+ "deploy-common.sh",
121
+ "deploy-development.sh",
122
+ "deploy-production.sh",
123
+ )
124
+ for name in executable_names:
125
+ target = scripts_dir / name
126
+ if target.is_file():
127
+ target.chmod(target.stat().st_mode | 0o111)
128
+ typer.echo(f"synced: {platform}/scripts (run refreshed; deploy preserved)")
108
129
 
109
130
 
110
131
  def sync_all(root: Path, *, force: bool = True) -> None:
@@ -31,7 +31,7 @@ def ensure_agent_wiring(root: Path, *, force: bool = False) -> None:
31
31
 
32
32
 
33
33
  def ensure_root_from_templates(root: Path, *, force: bool = False) -> None:
34
- """Copy root Makefile / TOOLS.md / .gitignore / make.bat from packaged templates."""
34
+ """Copy managed root templates and create the user-owned Diff.md once."""
35
35
  templates = paths.templates_dir()
36
36
  for name in (".gitignore", "Makefile", "make.bat", "TOOLS.md"):
37
37
  src = templates / name
@@ -39,3 +39,9 @@ def ensure_root_from_templates(root: Path, *, force: bool = False) -> None:
39
39
  typer.echo(f"warn: missing template: {src}", err=True)
40
40
  continue
41
41
  copy_file(src, root / name, force=force)
42
+
43
+ diff_src = templates / "Diff.md"
44
+ if not diff_src.is_file():
45
+ typer.echo(f"warn: missing template: {diff_src}", err=True)
46
+ else:
47
+ copy_file(diff_src, root / "Diff.md", skip_existing=True)
@@ -1,34 +0,0 @@
1
- # Platform targets are discovered from */scripts/run.sh (after yjcli platform add).
2
- # Usage:
3
- # make <platform> # all services under that platform (concurrent)
4
- # make <platform> NAME=<service> # one service
5
- # Extend this root file for repository-owned work when needed. A useful pattern
6
- # is <platform>-<action> with the same optional NAME selector, for example
7
- # `make backend-deploy [NAME=api]`. yjcli does not define those actions.
8
-
9
- PLATFORMS := $(patsubst %/scripts/run.sh,%,$(wildcard */scripts/run.sh))
10
-
11
- .PHONY: help $(PLATFORMS)
12
-
13
- help:
14
- @echo "Usage:"
15
- @echo " make <platform> # start all services concurrently"
16
- @echo " make <platform> NAME=<service> # start one service"
17
- @echo ""
18
- @echo "Available platforms (dirs with scripts/run.sh):"
19
- @if [ -z "$(PLATFORMS)" ]; then \
20
- echo " (none — run: yjcli platform add)"; \
21
- else \
22
- for p in $(PLATFORMS); do echo " $$p"; done; \
23
- fi
24
- @echo ""
25
- @echo "Example: make backend"
26
- @echo " make backend NAME=api"
27
-
28
- $(PLATFORMS):
29
- @test -x "$@/scripts/run.sh" || (echo "missing: $@/scripts/run.sh"; exit 1)
30
- @if [ -n "$(NAME)" ]; then \
31
- "$@/scripts/run.sh" "$(NAME)" $(ARGS); \
32
- else \
33
- "$@/scripts/run.sh" $(ARGS); \
34
- fi
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
File without changes