yjcli 0.1.4__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.
- {yjcli-0.1.4 → yjcli-0.2.0}/PKG-INFO +4 -2
- {yjcli-0.1.4 → yjcli-0.2.0}/README.md +3 -1
- {yjcli-0.1.4 → yjcli-0.2.0}/pyproject.toml +1 -1
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-arch-core/SKILL.md +3 -1
- yjcli-0.2.0/src/yjcli/data/skills/yj-scheduler/SKILL.md +124 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/AGENTS.md +1 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/modules/constants.py +2 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/services/scaffold.py +1 -1
- {yjcli-0.1.4 → yjcli-0.2.0}/.gitignore +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/LICENSE +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/__main__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/cli.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/commands/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/commands/init_cmd.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/commands/platform.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/commands/service.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/commands/sync.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-backend-msa/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-backend-service/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-browser-extension/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-cli/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-frontend/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-mobile-app/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/skills/yj-pc-app/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/.gitignore +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/Makefile +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/TOOLS.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/make.bat +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.development +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.examples +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.local-dev +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/app/.env.production +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.development +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.examples +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.local-dev +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/listen/.env.production +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.development +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.examples +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.local-dev +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/envs/worker/.env.production +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/frontend/package.json +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/frontend/vite.config.ts +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/scripts/run.bat +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/platform/scripts/run.sh +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/data/templates/settings.json +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/modules/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/modules/fsutil.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/modules/paths.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/modules/prompt.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/services/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/services/status.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.0}/src/yjcli/services/sync.py +0 -0
- {yjcli-0.1.4 → 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.
|
|
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
|
|
|
@@ -146,9 +146,11 @@ yjcli init --force
|
|
|
146
146
|
yjcli platform add
|
|
147
147
|
yjcli platform add --all
|
|
148
148
|
yjcli platform add -t cli
|
|
149
|
+
yjcli platform add -t scheduler
|
|
149
150
|
|
|
150
151
|
yjcli service add
|
|
151
152
|
yjcli service add -p backend -n api
|
|
153
|
+
yjcli service add -p scheduler -n operations
|
|
152
154
|
|
|
153
155
|
yjcli sync agents
|
|
154
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
|
|
|
@@ -121,9 +121,11 @@ yjcli init --force
|
|
|
121
121
|
yjcli platform add
|
|
122
122
|
yjcli platform add --all
|
|
123
123
|
yjcli platform add -t cli
|
|
124
|
+
yjcli platform add -t scheduler
|
|
124
125
|
|
|
125
126
|
yjcli service add
|
|
126
127
|
yjcli service add -p backend -n api
|
|
128
|
+
yjcli service add -p scheduler -n operations
|
|
127
129
|
|
|
128
130
|
yjcli sync agents
|
|
129
131
|
yjcli sync skills
|
|
@@ -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_
|
|
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":
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|