diff --git a/mateclaw-server/src/main/java/vip/mate/skill/manifest/SkillManifest.java b/mateclaw-server/src/main/java/vip/mate/skill/manifest/SkillManifest.java
new file mode 100644
index 00000000..aee6d099
--- /dev/null
+++ b/mateclaw-server/src/main/java/vip/mate/skill/manifest/SkillManifest.java
@@ -0,0 +1,192 @@
+package vip.mate.skill.manifest;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * RFC-090 Phase 2 — parsed SKILL.md manifest (source of truth, §14.6).
+ *
+ *
Maps the YAML frontmatter shape from §5.1 onto a typed model.
+ * Persisted to {@code mate_skill.manifest_json}; legacy columns
+ * (skill_type / icon / version / author) are projected from this
+ * after each resolve.
+ *
+ *
All collection fields default to empty so consumers don't need
+ * null guards. Unknown YAML keys are preserved in
+ * {@link #extras} for forward compatibility.
+ */
+@Data
+@Builder
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class SkillManifest {
+
+ // ==================== Identity ====================
+
+ private String id;
+ private String name;
+ private String description;
+ private String icon;
+ private String version;
+ private String author;
+
+ /** prompt | code | mcp | acp | knowledge */
+ private String type;
+
+ /** file | web | data | content | comm | system | ... (free-form tag) */
+ private String category;
+
+ // ==================== Tools / dependencies ====================
+
+ /** Anthropic-compatible {@code allowed-tools} list. */
+ @Builder.Default
+ private List allowedTools = List.of();
+
+ /** Top-level {@code requires} entries. */
+ @Builder.Default
+ private List requires = List.of();
+
+ /** Top-level {@code platforms} list (overall package compatibility). */
+ @Builder.Default
+ private List platforms = List.of();
+
+ /**
+ * v3.1 {@code features[]} matrix. Empty list means
+ * "no explicit feature partitioning" — the resolver synthesizes a
+ * single default feature carrying the top-level {@link #requires}
+ * and {@link #platforms} so legacy skills behave unchanged.
+ */
+ @Builder.Default
+ private List features = List.of();
+
+ // ==================== User-facing settings ====================
+
+ @Builder.Default
+ private List settings = List.of();
+
+ // ==================== Provider routing ====================
+
+ @Builder.Default
+ private List requiresModel = List.of();
+
+ // ==================== Dashboard ====================
+
+ @Builder.Default
+ private List dashboardMetrics = List.of();
+
+ // ==================== v3 self-evolution ====================
+
+ @Builder.Default
+ private SelfEvolution selfEvolution = SelfEvolution.defaults();
+
+ // ==================== v3.1 knowledge type ====================
+
+ private KnowledgeBinding knowledge;
+
+ // ==================== Forward-compat catch-all ====================
+
+ /** Unknown frontmatter keys are stashed here so a future field
+ * doesn't drop on parse — the JSON round-trips intact. */
+ @Builder.Default
+ private Map extras = Map.of();
+
+ // ==================== Nested types ====================
+
+ @Data
+ @Builder
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public static class RequirementDef {
+ /** Required: stable identifier referenced by {@code features[*].requires}. */
+ private String key;
+ /** binary | env_var | api_key */
+ private String type;
+ /** Probe target — for binary, the executable name; for env_var, the env name. */
+ private String check;
+ /** Optional means it only blocks features that reference it explicitly. */
+ @Builder.Default
+ private boolean optional = false;
+ private String description;
+ @Builder.Default
+ private Map install = Map.of();
+ }
+
+ @Data
+ @Builder
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public static class FeatureDef {
+ private String id;
+ private String label;
+ @Builder.Default
+ private List requires = List.of();
+ @Builder.Default
+ private List platforms = List.of();
+ /** Tools advertised only when this feature is READY. Empty
+ * means "inherit the manifest-level allowed-tools as-is". */
+ @Builder.Default
+ private List tools = List.of();
+ private String fallbackMessage;
+ private String unsupportedMessage;
+ }
+
+ @Data
+ @Builder
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public static class SettingDef {
+ private String key;
+ private String label;
+ /** select | text | secret | toggle */
+ private String type;
+ private Object defaultValue;
+ @Builder.Default
+ private List