@personaxis/spec 0.11.0
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/LICENSE +21 -0
- package/dist/generated/schemas.d.ts +5 -0
- package/dist/generated/schemas.js +7 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +416 -0
- package/package.json +34 -0
- package/schema/legacy/persona-0.10.schema.json +932 -0
- package/schema/memory.schema.json +48 -0
- package/schema/persona.schema.json +2095 -0
- package/schema/policy.schema.json +192 -0
- package/schema/state.schema.json +150 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://personaxis.com/schemas/persona/0.10/policy.schema.json",
|
|
4
|
+
"title": "policy.yaml v0.10",
|
|
5
|
+
"description": "Schema for the sibling policy.yaml file that lives next to personaxis.md inside .personaxis/[personas/<slug>/]. Encodes the operational policy the Personaxis platform enforces over a persona-version: behavioral assertions, runtime constraints, evaluation suites, and improvement_policy (mutation governance). policy.yaml is consumed by the Personaxis backend and dashboard; it is NEVER inlined into an LLM system prompt. v0.7 is a layout-only change (moved from repo-root to .personaxis/); v0.6 introduced the autonomous mode and explicit scope allowlist/blocklist for spec self-edits.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["spec_version", "applies_to", "improvement_policy"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"spec_version": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["1.0.0", "0.10.0", "0.9.0", "0.8.0", "0.7.0", "0.6.0", "0.5.0"],
|
|
13
|
+
"description": "Schema version, forward-compatible with the spec minors (policy.yaml has had no field changes since 0.6.0; 0.7.0 was layout-only). Accepts 0.6.0-0.10.0; 0.5.0 accepted for backward compatibility (auto-migrated)."
|
|
14
|
+
},
|
|
15
|
+
"applies_to": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"required": ["persona_name"],
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"description": "Reference to the personaxis.md this policy governs. Lets a registry hold multiple policy.yaml siblings for different version ranges of the same persona (rare, but supported).",
|
|
20
|
+
"properties": {
|
|
21
|
+
"persona_name": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$",
|
|
24
|
+
"description": "Must match the metadata.name of the personaxis.md in the same directory."
|
|
25
|
+
},
|
|
26
|
+
"persona_version_range": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Optional semver range (e.g. '>=1.0.0 <2.0.0'). When omitted, policy applies to all versions of the persona. Validator rejects when two policy.yaml files in the same registry have overlapping ranges for the same persona_name."
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"improvement_policy": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"required": ["mode"],
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"description": "Mutation governance. Controls whether the Personaxis platform may suggest or apply changes to the persona-version based on observed drift. Default mode 'locked' is the only safe choice for production-critical personas.",
|
|
37
|
+
"properties": {
|
|
38
|
+
"mode": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"enum": ["locked", "suggesting", "autonomous", "auto"],
|
|
41
|
+
"description": "locked (default; safest): PERSONA.md is immutable at runtime. state.json mutations within envelopes are still allowed. Drift alerts only. suggesting: actor MAY call propose_self_edit; proposals queued in dashboard for human approval; approval mints a new PersonaVersion. autonomous (high-risk): actor MAY call apply_self_edit directly; each applied edit creates a new PersonaVersion. Bound by universal invariants, governance.per_layer_edit_policy, hard_limits, and autonomous_scope_allowlist/blocklist. 'auto' is a deprecated alias for 'autonomous' (v0.5 compatibility)."
|
|
42
|
+
},
|
|
43
|
+
"autonomous_scope_allowlist": {
|
|
44
|
+
"type": "array",
|
|
45
|
+
"items": { "type": "string" },
|
|
46
|
+
"description": "Dot-notation paths the actor MAY auto-edit when mode='autonomous'. Wildcards allowed (e.g., 'persona.task_modes.*'). Required when mode='autonomous'."
|
|
47
|
+
},
|
|
48
|
+
"autonomous_scope_blocklist": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": { "type": "string" },
|
|
51
|
+
"description": "Dot-notation paths always blocked, even when mode='autonomous'. Wildcards allowed. Recommended to always include identity.*, character.virtues.*.enforcement, reflexive_self_regulation.*, values_and_drives.values.safety.*, governance.*, security.*."
|
|
52
|
+
},
|
|
53
|
+
"approved_by": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "User id or org id that authorized non-locked modes. Required by validator when mode != 'locked'."
|
|
56
|
+
},
|
|
57
|
+
"last_approval_at": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"format": "date-time",
|
|
60
|
+
"description": "Timestamp of the last human approval for non-locked modes. Required by validator when mode != 'locked'."
|
|
61
|
+
},
|
|
62
|
+
"approval_expires_at": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"format": "date-time",
|
|
65
|
+
"description": "Optional. If set, the platform reverts mode to 'locked' automatically after this timestamp. Encourages re-affirmation rather than indefinite consent."
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"allOf": [
|
|
69
|
+
{
|
|
70
|
+
"if": {
|
|
71
|
+
"properties": { "mode": { "enum": ["suggesting", "autonomous", "auto"] } }
|
|
72
|
+
},
|
|
73
|
+
"then": {
|
|
74
|
+
"required": ["mode", "approved_by", "last_approval_at"]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"if": {
|
|
79
|
+
"properties": { "mode": { "enum": ["autonomous", "auto"] } }
|
|
80
|
+
},
|
|
81
|
+
"then": {
|
|
82
|
+
"required": ["mode", "approved_by", "last_approval_at", "autonomous_scope_allowlist"]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"runtime": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"additionalProperties": false,
|
|
90
|
+
"description": "Runtime constraints declared by the spec author. Consumed by the Personaxis runtime and observability layer; opaque to the LLM actor.",
|
|
91
|
+
"properties": {
|
|
92
|
+
"min_consistency": {
|
|
93
|
+
"type": "number",
|
|
94
|
+
"minimum": 0,
|
|
95
|
+
"maximum": 1,
|
|
96
|
+
"description": "Drift status becomes 'regressed' if a layer's consistencyScore falls below this floor. Default 0.7 when omitted."
|
|
97
|
+
},
|
|
98
|
+
"drift_alert_channels": {
|
|
99
|
+
"type": "array",
|
|
100
|
+
"items": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"pattern": "^(slack|email|webhook|linear|pagerduty):"
|
|
103
|
+
},
|
|
104
|
+
"description": "Channel URIs (e.g. 'slack:#observability', 'webhook:https://...'). Resolved by the Personaxis dashboard, not by the spec runtime."
|
|
105
|
+
},
|
|
106
|
+
"allowed_consumers": {
|
|
107
|
+
"type": "array",
|
|
108
|
+
"items": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"enum": ["agent", "human", "mcp"]
|
|
111
|
+
},
|
|
112
|
+
"description": "Who may open a runtime session against this persona. Defaults to all three when omitted."
|
|
113
|
+
},
|
|
114
|
+
"compiled_prompt_cache_ttl_seconds": {
|
|
115
|
+
"type": "integer",
|
|
116
|
+
"minimum": 0,
|
|
117
|
+
"description": "Hint for the compiler's prompt-cache TTL (seconds). The compiler keys cached compiled prompts by (spec_hash, state_hash, context_hash). Default 300s. New in v0.6."
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"evaluation": {
|
|
122
|
+
"type": "object",
|
|
123
|
+
"additionalProperties": false,
|
|
124
|
+
"description": "Higher-order eval suites the persona-version must satisfy. Distinct from per-trace 'assertions': evaluation suites are batch runs over canonical prompt datasets (CI/CD gating, see Phase 2).",
|
|
125
|
+
"properties": {
|
|
126
|
+
"required_suites": {
|
|
127
|
+
"type": "array",
|
|
128
|
+
"items": { "type": "string" },
|
|
129
|
+
"description": "Named suites that must be present and passing for the version to be considered shippable. Suite definitions live in the registry."
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
"assertions": {
|
|
134
|
+
"type": "array",
|
|
135
|
+
"description": "Behavioral expectations evaluated at runtime by the Personaxis observability layer. Each assertion declares which spec layer it covers and how it is checked. The judge worker reads this block directly from the registry; it is NEVER inlined into the LLM system prompt.",
|
|
136
|
+
"items": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"required": ["layer", "name", "type", "definition", "severity"],
|
|
139
|
+
"additionalProperties": false,
|
|
140
|
+
"properties": {
|
|
141
|
+
"layer": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"enum": [
|
|
144
|
+
"identity",
|
|
145
|
+
"character",
|
|
146
|
+
"personality",
|
|
147
|
+
"values_and_drives",
|
|
148
|
+
"values_drives",
|
|
149
|
+
"affect",
|
|
150
|
+
"cognition",
|
|
151
|
+
"memory",
|
|
152
|
+
"metacognition",
|
|
153
|
+
"reflexive_self_regulation",
|
|
154
|
+
"persona",
|
|
155
|
+
"cross_layer"
|
|
156
|
+
],
|
|
157
|
+
"description": "One of the 10 canonical personaxis.md layers. The v0.6 canonical name for Layer 4 is 'values_and_drives'; 'values_drives' is accepted for backward compatibility with v0.5 policies. 'cross_layer' is for assertions that span multiple layers."
|
|
158
|
+
},
|
|
159
|
+
"name": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"minLength": 1,
|
|
162
|
+
"maxLength": 120,
|
|
163
|
+
"description": "Human-readable label shown in the dashboard."
|
|
164
|
+
},
|
|
165
|
+
"description": {
|
|
166
|
+
"type": "string",
|
|
167
|
+
"maxLength": 1000
|
|
168
|
+
},
|
|
169
|
+
"type": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"enum": ["regex", "semantic", "llm_judge", "activation_projection"],
|
|
172
|
+
"description": "Evaluation strategy. v0.5 runtime supports 'regex' and 'llm_judge' fully; 'semantic' and 'activation_projection' are reserved (no-op pass at evaluation time)."
|
|
173
|
+
},
|
|
174
|
+
"definition": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"description": "Type-specific configuration. Schema by type is documented in docs/personaxis-docs/architecture/observability-model.mdx.",
|
|
177
|
+
"additionalProperties": true
|
|
178
|
+
},
|
|
179
|
+
"severity": {
|
|
180
|
+
"type": "string",
|
|
181
|
+
"enum": ["info", "warn", "block"],
|
|
182
|
+
"description": "Drift weight: info=0.5, warn=1.0, block=2.0."
|
|
183
|
+
},
|
|
184
|
+
"enabled": {
|
|
185
|
+
"type": "boolean",
|
|
186
|
+
"description": "Defaults to true. Set false to retain the assertion in policy.yaml but skip evaluation."
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://personaxis.com/schemas/state/1.0/state.schema.json",
|
|
4
|
+
"title": "state.json v1.0",
|
|
5
|
+
"description": "Mutable runtime state of an AI Persona. Sibling of personaxis.md inside .personaxis/[personas/<slug>/]. Holds current trait/affect/mood values, active context, and the mutation log. Mutations occur via the canonical adjust_persona_state tool, clamped to envelopes declared in personaxis.md. State mutations DO NOT modify personaxis.md or the compiled PERSONA.md/<slug>.md; they are operational, not spec edits. v1.0 (D4): the mutable surface is EXACTLY the set of fields that declare a {mean, range} envelope in personaxis.md; values keys are FULL dot-paths into the spec; and state.json is a CHECKPOINT derived from mutation_log — a conforming runtime can rebuild values by replaying the log from the envelope means.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"schema_version",
|
|
9
|
+
"persona_id",
|
|
10
|
+
"persona_version",
|
|
11
|
+
"values"
|
|
12
|
+
],
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"properties": {
|
|
15
|
+
"schema_version": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"enum": ["1.0.0", "0.9.0", "0.8.0", "0.7.0", "0.6.0"],
|
|
18
|
+
"description": "state.json schema version. 1.0.0 is current (values keys are full dot-paths; state is a replayable checkpoint of mutation_log). 0.x accepted during the 1.x read-compat window."
|
|
19
|
+
},
|
|
20
|
+
"persona_id": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$",
|
|
23
|
+
"description": "Must match metadata.name in personaxis.md."
|
|
24
|
+
},
|
|
25
|
+
"persona_version": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
|
|
28
|
+
"description": "Must match metadata.version in personaxis.md at compile time. Used by the compiler to detect spec/state mismatch."
|
|
29
|
+
},
|
|
30
|
+
"session_id": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Optional session identifier. Useful when state is per-session rather than persisted across sessions."
|
|
33
|
+
},
|
|
34
|
+
"values": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"description": "Current values for all mutable fields. v1.0: keys are FULL dot-notation paths into personaxis.md ('personality.traits.openness', 'affect.baseline.core_affect.valence', 'affect.baseline.mood.tone', 'values_and_drives.drives.complete_task') and the key set is exactly the fields that declare a {mean, range} envelope. The short ≤0.10 forms ('traits.openness', 'affect.valence', 'mood.tone', 'drives.x') are legacy; conforming runtimes accept them as read-aliases during the 1.x window (the CLI's `migrate 0.10-to-1.0` renames them). Each value is a number that must lie within the envelope declared at the corresponding path; the runtime clamps any out-of-envelope value at mutation time.",
|
|
37
|
+
"additionalProperties": {
|
|
38
|
+
"type": "number"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"active_context": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"description": "Current contextual selectors that drive cold-slice injection in the compiled prompt.",
|
|
44
|
+
"additionalProperties": false,
|
|
45
|
+
"properties": {
|
|
46
|
+
"task_mode": {
|
|
47
|
+
"type": ["string", "null"],
|
|
48
|
+
"description": "Active task mode key. Must match a key in persona.task_modes, or null when no specific task is detected."
|
|
49
|
+
},
|
|
50
|
+
"audience": {
|
|
51
|
+
"type": ["string", "null"],
|
|
52
|
+
"description": "Active audience key. Must match a key in persona.audience_adaptation, or null when audience is undetermined."
|
|
53
|
+
},
|
|
54
|
+
"additional_context_flags": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": { "type": "string" },
|
|
57
|
+
"description": "Per-persona context flags (e.g., 'high_pressure', 'creative_review'). Used by the compiler to optionally inject extra cold slices."
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"memory_anchors_active": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": { "type": "string" },
|
|
64
|
+
"description": "List of active memory anchor IDs. The compiler uses these to inject high-priority memory references into the compiled prompt. Maintained by the runtime via retrieval policies."
|
|
65
|
+
},
|
|
66
|
+
"mutation_log": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"description": "Append-only log of every state mutation. Provides audit trail. The runtime trims old entries based on retention policy.",
|
|
69
|
+
"items": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"required": ["ts", "field", "from", "to", "actor"],
|
|
72
|
+
"additionalProperties": false,
|
|
73
|
+
"properties": {
|
|
74
|
+
"ts": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"format": "date-time",
|
|
77
|
+
"description": "ISO 8601 timestamp of the mutation."
|
|
78
|
+
},
|
|
79
|
+
"field": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"description": "Dot-notation path of the mutated field (matches a key in values)."
|
|
82
|
+
},
|
|
83
|
+
"from": {
|
|
84
|
+
"type": "number",
|
|
85
|
+
"description": "Previous value."
|
|
86
|
+
},
|
|
87
|
+
"to": {
|
|
88
|
+
"type": "number",
|
|
89
|
+
"description": "New value (post-clamp)."
|
|
90
|
+
},
|
|
91
|
+
"delta_requested": {
|
|
92
|
+
"type": "number",
|
|
93
|
+
"description": "Original delta requested. May differ from (to - from) if clamping occurred."
|
|
94
|
+
},
|
|
95
|
+
"clamped": {
|
|
96
|
+
"type": "boolean",
|
|
97
|
+
"description": "True if the requested mutation was clamped to envelope. The actor receives clamped=true to signal the floor/ceiling was reached."
|
|
98
|
+
},
|
|
99
|
+
"reason": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"description": "Human-readable rationale for the mutation."
|
|
102
|
+
},
|
|
103
|
+
"actor": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"enum": ["actor-llm", "runtime-decay", "runtime-context", "human-operator", "judge-correction"],
|
|
106
|
+
"description": "Which subsystem triggered the mutation."
|
|
107
|
+
},
|
|
108
|
+
"tool_call_id": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "ID of the adjust_persona_state tool call that produced this mutation, if applicable."
|
|
111
|
+
},
|
|
112
|
+
"governance_blocked": {
|
|
113
|
+
"type": "boolean",
|
|
114
|
+
"description": "True if the mutation was rejected by governance (e.g., hard-enforced virtue, hard limit, scope blocklist). When true, from === to and reason explains the block."
|
|
115
|
+
},
|
|
116
|
+
"origin_node": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "v0.8: stable id of the machine/instance that produced this mutation. Makes cross-OS reconciliation of a portable persona deterministic (last-writer-wins per field across machines)."
|
|
119
|
+
},
|
|
120
|
+
"session_id": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"description": "v0.8: id of the runtime session that produced this mutation, for traceability."
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"last_compiled_at": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"format": "date-time",
|
|
130
|
+
"description": "Timestamp of the last compilation that consumed this state. Used by cache invalidation."
|
|
131
|
+
},
|
|
132
|
+
"last_compiled_hash": {
|
|
133
|
+
"type": "string",
|
|
134
|
+
"description": "Hash of the inputs that produced the last compiled prompt. Used by cache invalidation."
|
|
135
|
+
},
|
|
136
|
+
"agent_session": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"additionalProperties": false,
|
|
139
|
+
"description": "v0.9: live agent-loop session tracking. Lets a task resume across runs and records budget spend + why the loop stopped.",
|
|
140
|
+
"properties": {
|
|
141
|
+
"active_task": { "type": ["string", "null"], "description": "The task currently being executed, or null when idle." },
|
|
142
|
+
"started_at": { "type": ["string", "null"], "format": "date-time" },
|
|
143
|
+
"step_count": { "type": "integer", "minimum": 0 },
|
|
144
|
+
"token_count": { "type": "integer", "minimum": 0 },
|
|
145
|
+
"cost_usd": { "type": "number", "minimum": 0 },
|
|
146
|
+
"stop_reason": { "type": ["string", "null"], "description": "Why the last run stopped (goal_met, max_steps, max_tokens, verification_failed, …)." }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|