@antprofuse/saddle-skill 0.1.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/SKILL.md ADDED
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: saddle-service
3
+ description: Build and review minimal Rust Service applications against the published Saddle facade package `saddle-framework = "=0.1.1"`. Use when Codex needs to create a Saddle 0.1.1 Service contract, handler, registration, HTTP/JSON exposure, fixed process entry, or verify generated business code without reading or changing Saddle middleware implementation.
4
+ ---
5
+
6
+ # Saddle Service 0.1.1
7
+
8
+ Use only the public API shipped by `saddle-framework = "=0.1.1"`.
9
+
10
+ ## Workflow
11
+
12
+ 1. Pin the facade exactly as `saddle-framework = "=0.1.1"`; import it as `saddle`.
13
+ 2. Read [references/service-0.1.1.md](references/service-0.1.1.md) before generating Service code.
14
+ 3. Start from the verified `examples/helloworld` consumer when working in the Saddle repository.
15
+ 4. Keep business code limited to request/response types, a Service contract, its handler, and Saddle assembly.
16
+ 5. Run both the Rust 1.85 and current-toolchain checks documented in [references/service-0.1.1.md](references/service-0.1.1.md) after changing the reference example.
17
+ 6. Reject APIs that are only described as V1 goals but are absent from the published facade.
18
+
19
+ ## Boundaries
20
+
21
+ - Do not inspect or modify Saddle component implementation.
22
+ - Do not replace Saddle's process entry, async runtime, HTTP server, database pool, or observability setup.
23
+ - Do not create threads, runtimes, detached tasks, routers, I/O clients, or DB pools in business code.
24
+ - Do not claim DB, transaction, internal Service call, graceful shutdown, or observability usage patterns without a compiling 0.1.1 consumer.
25
+ - If a required public API is missing, preserve a minimal reproducible consumer failure and submit it through remote Git for the control workspace to assess. Do not patch middleware here.
26
+ - Treat local design documents as intent and crates.io 0.1.1 compilation as the source of truth for usable API.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Saddle Service 0.1.1"
3
+ short_description: "Build verified Saddle 0.1.1 Service applications"
4
+ default_prompt: "Use $saddle-service to build a minimal Saddle Service application."
package/package.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@antprofuse/saddle-skill",
3
+ "version": "0.1.1",
4
+ "description": "AI Coding skill for building verified Saddle 0.1.1 Service applications.",
5
+ "license": "MIT OR Apache-2.0",
6
+ "files": [
7
+ "SKILL.md",
8
+ "agents",
9
+ "references"
10
+ ],
11
+ "publishConfig": {
12
+ "access": "public",
13
+ "registry": "https://registry.npmjs.org/"
14
+ }
15
+ }
@@ -0,0 +1,163 @@
1
+ # Saddle Service 0.1.1 contract
2
+
3
+ ## Dependency
4
+
5
+ Use the published facade package at an exact version:
6
+
7
+ ```toml
8
+ [package]
9
+ edition = "2024"
10
+ rust-version = "1.85"
11
+
12
+ [dependencies]
13
+ saddle-framework = "=0.1.1"
14
+ serde = { version = "1", features = ["derive"] }
15
+ ```
16
+
17
+ The Cargo package is `saddle-framework`; the Rust library name is `saddle`.
18
+
19
+ ## Correct minimal pattern
20
+
21
+ Define one zero-sized contract type, serializable request/response types, and a separate handler:
22
+
23
+ ```rust
24
+ use saddle::{
25
+ CallContext,
26
+ service::{Service, ServiceFuture, ServiceHandler},
27
+ };
28
+ use serde::{Deserialize, Serialize};
29
+
30
+ struct Hello;
31
+
32
+ #[derive(Deserialize)]
33
+ struct HelloRequest {
34
+ name: String,
35
+ }
36
+
37
+ #[derive(Serialize)]
38
+ struct HelloResponse {
39
+ message: String,
40
+ }
41
+
42
+ impl Service for Hello {
43
+ type Request = HelloRequest;
44
+ type Response = HelloResponse;
45
+ }
46
+
47
+ struct HelloHandler;
48
+
49
+ impl ServiceHandler<Hello> for HelloHandler {
50
+ fn call<'a>(
51
+ &'a self,
52
+ _context: &'a CallContext,
53
+ request: HelloRequest,
54
+ ) -> ServiceFuture<'a, HelloResponse> {
55
+ Box::pin(async move {
56
+ Ok(HelloResponse {
57
+ message: format!("Hello, {}!", request.name),
58
+ })
59
+ })
60
+ }
61
+ }
62
+ ```
63
+
64
+ Register and expose it only through Saddle:
65
+
66
+ ```rust
67
+ builder.register::<Hello, _>(
68
+ ServiceDescriptor::new("helloworld", "hello", "say_hello"),
69
+ HelloHandler,
70
+ )?;
71
+ builder.expose_json::<Hello>("/hello");
72
+ ```
73
+
74
+ Use the fixed process entry:
75
+
76
+ ```rust
77
+ let database_url = std::env::var("SADDLE_DATABASE_URL")
78
+ .expect("SADDLE_DATABASE_URL must be set by deployment configuration");
79
+ let config = SaddleConfig::new("helloworld", database_url, listen);
80
+
81
+ Saddle::run(config, |builder| {
82
+ // Register and expose Services here.
83
+ Ok(())
84
+ })
85
+ ```
86
+
87
+ See `examples/helloworld` for the complete compiling consumer.
88
+
89
+ ## Incorrect patterns
90
+
91
+ Do not use an unpinned or compatible version range:
92
+
93
+ ```toml
94
+ # Wrong: 0.1.x may change incompatibly.
95
+ saddle-framework = "0.1"
96
+ ```
97
+
98
+ Do not embed database credentials or provide an insecure fallback:
99
+
100
+ ```rust
101
+ // Wrong: canonical examples must not normalize secrets in source.
102
+ let database_url = "mysql://user:password@127.0.0.1/application";
103
+
104
+ // Wrong: a missing deployment value must fail instead of silently using credentials.
105
+ let database_url = std::env::var("SADDLE_DATABASE_URL")
106
+ .unwrap_or_else(|_| "mysql://user:password@127.0.0.1/application".into());
107
+ ```
108
+
109
+ Do not import Service traits from the facade root:
110
+
111
+ ```rust
112
+ // Wrong in 0.1.1: these are under saddle::service.
113
+ use saddle::{Service, ServiceHandler};
114
+ ```
115
+
116
+ Do not implement business execution with Tokio or Axum:
117
+
118
+ ```rust
119
+ // Wrong: business code must not own the runtime or HTTP server.
120
+ #[tokio::main]
121
+ async fn main() {}
122
+
123
+ tokio::spawn(async move {});
124
+ axum::Router::new();
125
+ ```
126
+
127
+ Do not invent ergonomic macros or async trait syntax that 0.1.1 does not publish:
128
+
129
+ ```rust
130
+ // Wrong: not verified public APIs in 0.1.1.
131
+ #[saddle::service]
132
+ async fn hello(...) { ... }
133
+
134
+ #[saddle::main]
135
+ async fn main() { ... }
136
+ ```
137
+
138
+ Do not create a registry or database directly:
139
+
140
+ ```rust
141
+ // Wrong: assembly and managed I/O construction belong to Saddle.
142
+ let registry = saddle::service::ServiceRegistryBuilder::new();
143
+ let database = saddle::db::Database::connect(...);
144
+ ```
145
+
146
+ ## Validation
147
+
148
+ Run:
149
+
150
+ ```bash
151
+ cargo +1.85.0 check --locked --manifest-path examples/helloworld/Cargo.toml
152
+ cargo check --locked --manifest-path examples/helloworld/Cargo.toml
153
+ cargo tree --locked --manifest-path examples/helloworld/Cargo.toml \
154
+ -p saddle-framework@0.1.1
155
+ ```
156
+
157
+ Current verified result:
158
+
159
+ - The Rust 1.85 and current-toolchain checks compile against the crates.io `saddle-framework 0.1.1` artifact.
160
+ - The dependency tree resolves every Saddle component to 0.1.1.
161
+ - The lockfile is resolved with Cargo 1.85's incompatible-Rust-version fallback so every selected package supports the declared minimum.
162
+
163
+ The example does not prove runtime readiness because `SADDLE_DATABASE_URL` must identify a reachable database and the configured listen address must be available.