@kindgi/specs 0.0.0-bootstrap.0 → 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.
@@ -0,0 +1,261 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://kindgi.com/schemas/v1/guardrail.schema.json",
4
+ "$comment": "schema-version: 1.1.0",
5
+ "title": "Guardrail",
6
+ "description": "An assertion about agent behavior. Enforced at runtime (halt / retry / escalate / log-only / compensate per guardrail) AND in CI (blocks builds). Same definition, two enforcement paths — no drift between what tests check and what prod enforces. Zero-LLM checks are default (fast, deterministic); LLM-judge scorers are an opt-in class with explicit cost declaration. Schema-version 1.1.0 matches the `Guardrail` type: `check` is required, a `retry` action needs `maxAttempts`, `kind` and `on-violation` accept any non-empty string (the built-ins are listed as `examples`), and `sandbox` / `limits` / `network` / `needsSpec` are allowed.",
7
+ "type": "object",
8
+ "required": ["id", "kind", "check", "action"],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "id": {
12
+ "type": "string",
13
+ "minLength": 1,
14
+ "description": "Unique guardrail identifier."
15
+ },
16
+ "name": {
17
+ "type": "string",
18
+ "description": "Human-readable name."
19
+ },
20
+ "description": {
21
+ "type": "string",
22
+ "description": "What this guardrail guarantees, and what happens if violated."
23
+ },
24
+ "kind": {
25
+ "type": "string",
26
+ "minLength": 1,
27
+ "examples": ["zero-llm", "llm-judge", "external"],
28
+ "description": "How the guardrail is checked. Open string: the engine dispatches it to the execution strategy registered for that kind, and `defineGuardrail` requires a registered check of the same kind. Built-in kinds: 'zero-llm' = pure function over run trace (default, fast, deterministic). 'llm-judge' = uses a model to score (opt-in, costs money). 'external' = evaluated outside the engine by a caller-registered strategy (the built-in 'external' strategy returns an error). Adapters can register strategies for their own kinds."
29
+ },
30
+ "check": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "description": "Id of the check in the CheckRegistry. For zero-llm: a built-in check ('must-cite', 'never-call-tool', 'max-tool-calls', 'output-matches', 'tool-order', 'required-substring', 'forbidden-substring') or a custom check id. For llm-judge: the id of a registered check of kind 'llm-judge' (the judge is configured by config and judgeCapabilities). For external and adapter kinds: an id the kind's strategy understands. Required since schema-version 1.1.0 (`defineGuardrail` already failed without a registered check)."
34
+ },
35
+ "config": {
36
+ "type": "object",
37
+ "additionalProperties": true,
38
+ "description": "Check-specific configuration. Interpreted by the check implementation."
39
+ },
40
+ "action": {
41
+ "$ref": "#/$defs/Action"
42
+ },
43
+ "severity": {
44
+ "type": "string",
45
+ "enum": ["info", "warn", "error", "critical"],
46
+ "default": "error"
47
+ },
48
+ "scope": {
49
+ "$ref": "#/$defs/Scope",
50
+ "description": "When this guardrail applies: 'always' (every run), 'ci-only' (blocks CI, not runtime), 'runtime-only' (runtime enforcement, not CI), or a per-agent/per-flow selector."
51
+ },
52
+ "budget": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "description": "For llm-judge guardrails: cost budget per invocation. Declarative — not enforced by the runtime.",
56
+ "properties": {
57
+ "maxCostUsd": {
58
+ "type": "number",
59
+ "minimum": 0
60
+ },
61
+ "maxLatencyMs": {
62
+ "type": "integer",
63
+ "minimum": 0
64
+ }
65
+ }
66
+ },
67
+ "sandbox": {
68
+ "type": "string",
69
+ "enum": ["none", "context-isolated", "strict"],
70
+ "description": "Isolation posture the runtime enforces around the check's handler. Same values as a tool's `sandbox`. Added in schema-version 1.1.0."
71
+ },
72
+ "limits": {
73
+ "type": "object",
74
+ "additionalProperties": false,
75
+ "description": "Sandbox-enforced resource caps while the check runs. Same shape as a tool's `limits`. Added in schema-version 1.1.0.",
76
+ "properties": {
77
+ "memMB": {
78
+ "type": "integer",
79
+ "minimum": 1
80
+ },
81
+ "cpuMs": {
82
+ "type": "integer",
83
+ "minimum": 1
84
+ }
85
+ },
86
+ "required": ["memMB", "cpuMs"]
87
+ },
88
+ "network": {
89
+ "type": "object",
90
+ "description": "Network egress policy the sandbox honors while the check runs. Discriminated on `kind`; same shape as a tool's `network`. Added in schema-version 1.1.0.",
91
+ "oneOf": [
92
+ {
93
+ "type": "object",
94
+ "additionalProperties": false,
95
+ "properties": {
96
+ "kind": {
97
+ "type": "string",
98
+ "enum": ["none", "unrestricted"]
99
+ }
100
+ },
101
+ "required": ["kind"]
102
+ },
103
+ {
104
+ "type": "object",
105
+ "additionalProperties": false,
106
+ "properties": {
107
+ "kind": {
108
+ "type": "string",
109
+ "const": "allowlist"
110
+ },
111
+ "hosts": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string",
115
+ "minLength": 1
116
+ }
117
+ }
118
+ },
119
+ "required": ["kind", "hosts"]
120
+ }
121
+ ]
122
+ },
123
+ "needsSpec": {
124
+ "type": "object",
125
+ "additionalProperties": false,
126
+ "description": "Typed discriminated needs of the check (env / secrets / config / capabilities / bindings). Same shape as a tool's `needsSpec`. Added in schema-version 1.1.0.",
127
+ "properties": {
128
+ "env": {
129
+ "type": "object",
130
+ "additionalProperties": {
131
+ "type": "object"
132
+ }
133
+ },
134
+ "secrets": {
135
+ "type": "object",
136
+ "additionalProperties": {
137
+ "type": "object"
138
+ }
139
+ },
140
+ "config": {
141
+ "type": "object",
142
+ "additionalProperties": {
143
+ "type": "object"
144
+ }
145
+ },
146
+ "capabilities": {
147
+ "type": "array",
148
+ "items": {
149
+ "type": "string",
150
+ "minLength": 1
151
+ }
152
+ },
153
+ "bindings": {
154
+ "type": "array",
155
+ "items": {
156
+ "type": "string",
157
+ "minLength": 1
158
+ }
159
+ }
160
+ }
161
+ },
162
+ "codeArtifactRef": {
163
+ "description": "Handler-artifact pointer for the guardrail's check implementation. Discriminated on `kind`: `oci` is the deploy-pipeline shape (image + module path + artifactVersion); `filesystem` is the local-development shape — absolute host path at the check module. Production servers SHOULD reject `filesystem`.",
164
+ "oneOf": [
165
+ {
166
+ "type": "object",
167
+ "additionalProperties": false,
168
+ "properties": {
169
+ "kind": { "const": "oci" },
170
+ "imageRef": { "type": "string", "minLength": 1 },
171
+ "modulePath": { "type": "string", "minLength": 1 },
172
+ "artifactVersion": { "type": "string", "minLength": 1 }
173
+ },
174
+ "required": ["kind", "imageRef", "modulePath", "artifactVersion"]
175
+ },
176
+ {
177
+ "type": "object",
178
+ "additionalProperties": false,
179
+ "properties": {
180
+ "kind": { "const": "filesystem" },
181
+ "modulePath": { "type": "string", "minLength": 1 }
182
+ },
183
+ "required": ["kind", "modulePath"]
184
+ }
185
+ ]
186
+ },
187
+ "judgeCapabilities": {
188
+ "type": "object",
189
+ "description": "For llm-judge guardrails: capability declaration for the judge model. Routed through `@kindgi/capabilities` over the providers bound for evaluation; when the caller passes a tenant policy (an agent turn passes its own), the judge is routed under it. BYO judges supported.",
190
+ "additionalProperties": true
191
+ }
192
+ },
193
+ "$defs": {
194
+ "Action": {
195
+ "type": "object",
196
+ "required": ["on-violation"],
197
+ "additionalProperties": false,
198
+ "properties": {
199
+ "on-violation": {
200
+ "type": "string",
201
+ "minLength": 1,
202
+ "examples": ["halt", "retry", "escalate", "log-only", "compensate"],
203
+ "description": "What happens when the guardrail fires. Open string: any non-empty name is accepted here, and an action handler registered under that name applies it; when the caller evaluates with an action-handler registry, a name with no handler fails with `unknown-action`. Built-in actions: 'halt' = fail the run. 'retry' = re-execute the step (needs `retry.maxAttempts`). 'escalate' = route to HITL review. 'log-only' = record but don't block. 'compensate' = invoke a compensation action."
204
+ },
205
+ "retry": {
206
+ "type": "object",
207
+ "additionalProperties": false,
208
+ "description": "For on-violation = 'retry'.",
209
+ "required": ["maxAttempts"],
210
+ "properties": {
211
+ "maxAttempts": {
212
+ "type": "integer",
213
+ "minimum": 1,
214
+ "maximum": 10
215
+ }
216
+ }
217
+ },
218
+ "escalateTo": {
219
+ "type": "string",
220
+ "description": "For on-violation = 'escalate': reviewer role or queue id."
221
+ },
222
+ "compensateWith": {
223
+ "type": "string",
224
+ "description": "For on-violation = 'compensate': tool id to invoke as compensation."
225
+ }
226
+ }
227
+ },
228
+ "Scope": {
229
+ "type": "object",
230
+ "additionalProperties": false,
231
+ "properties": {
232
+ "when": {
233
+ "type": "string",
234
+ "enum": ["always", "ci-only", "runtime-only"],
235
+ "default": "always"
236
+ },
237
+ "agents": {
238
+ "type": "array",
239
+ "items": {
240
+ "type": "string"
241
+ },
242
+ "description": "Agent ids this guardrail applies to. Empty = all agents."
243
+ },
244
+ "flows": {
245
+ "type": "array",
246
+ "items": {
247
+ "type": "string"
248
+ },
249
+ "description": "Flow ids this guardrail applies to. Empty = all flows."
250
+ },
251
+ "tenants": {
252
+ "type": "array",
253
+ "items": {
254
+ "type": "string"
255
+ },
256
+ "description": "Tenant ids this guardrail applies to. Empty = all tenants."
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }
@@ -0,0 +1,283 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://kindgi.com/schemas/v1/memory.schema.json",
4
+ "$comment": "schema-version: 1.3.0",
5
+ "title": "Memory — Log + Facts",
6
+ "description": "Two memory primitives: LogEntry (append-only event stream — turns, tool calls, tool results, agent internal messages) and Fact (typed, versioned records with declared retrieval hints). Views like message history, working memory, and semantic recall are queries over these two. Everything is tenant-scoped; scope is explicit and pluggable (tenant / user / org / project / thread / session). Log entries form a tamper-evident hash chain per (tenantId, runId) so any modification cascades — see LogEntry.prevHash / entryHash.",
7
+ "oneOf": [
8
+ {
9
+ "$ref": "#/$defs/LogEntry"
10
+ },
11
+ {
12
+ "$ref": "#/$defs/Fact"
13
+ }
14
+ ],
15
+ "$defs": {
16
+ "Scope": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["tenantId"],
20
+ "description": "Every memory item is scoped. Reads and writes must present a scope; the policy engine denies out-of-scope operations at the boundary.",
21
+ "properties": {
22
+ "tenantId": {
23
+ "type": "string",
24
+ "minLength": 1
25
+ },
26
+ "userId": {
27
+ "type": "string"
28
+ },
29
+ "orgId": {
30
+ "type": "string"
31
+ },
32
+ "projectId": {
33
+ "type": "string",
34
+ "description": "Project scope — whatever unit of work a pack organizes its memory around; the memory layer stays neutral about what it represents."
35
+ },
36
+ "threadId": {
37
+ "type": "string"
38
+ },
39
+ "sessionId": {
40
+ "type": "string"
41
+ }
42
+ }
43
+ },
44
+ "LogEntry": {
45
+ "type": "object",
46
+ "title": "LogEntry",
47
+ "description": "One event in the append-only log for a run/thread/session. Immutable once written. Ordered by (sequence, timestamp). Every entry commits to a hash of the previous entry in the same (tenantId, runId) — tamper with any past entry and every subsequent entry's prevHash breaks.",
48
+ "required": [
49
+ "id",
50
+ "kind",
51
+ "scope",
52
+ "timestamp",
53
+ "sequence",
54
+ "runId",
55
+ "prevHash",
56
+ "entryHash"
57
+ ],
58
+ "additionalProperties": false,
59
+ "properties": {
60
+ "id": {
61
+ "type": "string",
62
+ "minLength": 1
63
+ },
64
+ "kind": {
65
+ "type": "string",
66
+ "enum": [
67
+ "user-message",
68
+ "agent-message",
69
+ "system-message",
70
+ "tool-call",
71
+ "tool-result",
72
+ "internal-thought",
73
+ "retrieval",
74
+ "artifact-produced",
75
+ "event-emitted",
76
+ "event-received",
77
+ "guardrail-triggered",
78
+ "wait-suspended",
79
+ "wait-resumed"
80
+ ]
81
+ },
82
+ "scope": {
83
+ "$ref": "#/$defs/Scope"
84
+ },
85
+ "runId": {
86
+ "type": "string",
87
+ "description": "Kernel run that produced this entry."
88
+ },
89
+ "actor": {
90
+ "type": "string",
91
+ "description": "Who produced this entry (user id, agent id, tool id, or 'system')."
92
+ },
93
+ "timestamp": {
94
+ "type": "string",
95
+ "format": "date-time"
96
+ },
97
+ "sequence": {
98
+ "type": "integer",
99
+ "minimum": 0,
100
+ "description": "Monotonic sequence within (tenantId, runId). Enables deterministic replay ordering. Together with prevHash defines the tamper-evident chain within a run."
101
+ },
102
+ "payload": {
103
+ "description": "Kind-specific payload. Consumers must tolerate unknown fields."
104
+ },
105
+ "contentHash": {
106
+ "type": "string",
107
+ "pattern": "^sha256:[0-9a-f]{64}$",
108
+ "description": "Optional SHA-256 of the payload alone (independent of the chain), useful for content-addressed dedup."
109
+ },
110
+ "prevHash": {
111
+ "type": "string",
112
+ "pattern": "^sha256:[0-9a-f]{64}$",
113
+ "description": "SHA-256 of the previous LogEntry in the same (tenantId, runId) chain. The first entry (sequence=0) uses the zero-hash 'sha256:0000000000000000000000000000000000000000000000000000000000000000'. Added in schema-version 1.2.0."
114
+ },
115
+ "entryHash": {
116
+ "type": "string",
117
+ "pattern": "^sha256:[0-9a-f]{64}$",
118
+ "description": "SHA-256 of this entry's canonical serialization (id + kind + scope + runId + actor + timestamp + sequence + payload + prevHash). Used as the prevHash of the next entry in the chain. Added in schema-version 1.2.0."
119
+ },
120
+ "causedByLogId": {
121
+ "type": "string",
122
+ "description": "Optional link to the log entry that caused this one. Feeds the provenance DAG directly."
123
+ }
124
+ }
125
+ },
126
+ "Fact": {
127
+ "type": "object",
128
+ "title": "Fact",
129
+ "description": "A typed, versioned record. Facts are the durable, retrievable memory. Two flavors are expressible via the same primitive: (A) immutable outputs the runtime wrote from an agent run — versioned by supersession, no freshness semantics; (B) cached views of external state — carry an optional `source` block describing where the ground truth lives and how to refresh. Views (working memory, semantic recall, cross-history search) are queries over facts. Retrieval strategy (which indexes populate for a given `type`) is declared by pack authors via a policy registry, not per-instance — see `RetrievalPolicyRegistry` in @kindgi/memory. Schema-version 1.3.0 removed the per-instance `retrieve` hint that used to live on this record.",
130
+ "required": ["id", "type", "scope", "version", "createdAt"],
131
+ "additionalProperties": false,
132
+ "properties": {
133
+ "id": {
134
+ "type": "string",
135
+ "minLength": 1
136
+ },
137
+ "type": {
138
+ "type": "string",
139
+ "minLength": 1,
140
+ "description": "Fact type identifier. Vertical packs define their own; a few general-purpose names are conventional ('working-memory', 'user-profile', 'summary', 'entity-index')."
141
+ },
142
+ "scope": {
143
+ "$ref": "#/$defs/Scope"
144
+ },
145
+ "version": {
146
+ "type": "integer",
147
+ "minimum": 1,
148
+ "description": "Monotonic version within (scope, id). New writes increment; old versions are retained until retention policy expires them."
149
+ },
150
+ "createdAt": {
151
+ "type": "string",
152
+ "format": "date-time"
153
+ },
154
+ "updatedAt": {
155
+ "type": "string",
156
+ "format": "date-time"
157
+ },
158
+ "content": {
159
+ "description": "The fact payload — inline JSON. Optional since schema-version 1.1.0: if `contentRef` is set, the payload lives in blob storage and `content` may hold a summary or fingerprint for cheap retrieval-scoring. Rule of thumb: keep `content` ≤ ~64 KB inline; larger goes to blob."
160
+ },
161
+ "contentRef": {
162
+ "type": "string",
163
+ "description": "Optional (schema-version 1.1.0+): reference to a blob holding the actual bytes when they're too large to store inline. Format: 'blob://<provider>/<bucket>/<key>'. Consumers fetch it through the blob storage binding (`BlobStorageBinding.get()` in `@kindgi/blob-binding`)."
164
+ },
165
+ "contentHash": {
166
+ "type": "string",
167
+ "pattern": "^sha256:[0-9a-f]{64}$"
168
+ },
169
+ "size": {
170
+ "type": "integer",
171
+ "minimum": 0,
172
+ "description": "Optional (schema-version 1.1.0+): payload size in bytes. Populated by the writer; enables cheap size-based retrieval decisions without fetching the payload."
173
+ },
174
+ "embeddingModel": {
175
+ "type": "string",
176
+ "description": "For facts whose type-policy includes semantic indexing: the model used to embed. Enables re-indexing when the model changes."
177
+ },
178
+ "retention": {
179
+ "$ref": "#/$defs/Retention"
180
+ },
181
+ "source": {
182
+ "$ref": "#/$defs/Source",
183
+ "description": "Optional (schema-version 1.1.0+): present iff this fact is a cached view of external state (Kind B) rather than immutable runtime output (Kind A). Carries freshness metadata and a refresh strategy so readers can distinguish live-cached facts from historical facts."
184
+ },
185
+ "causedByLogId": {
186
+ "type": "array",
187
+ "items": {
188
+ "type": "string",
189
+ "minLength": 1
190
+ },
191
+ "minItems": 1,
192
+ "description": "Log entries that caused this fact write, in temporal order. Every fact traces back to at least one causal event. Multi-source facts (consolidation, extraction over many messages, cross-fact synthesis) list all source log ids; single-source facts list one. Widened from string → string[] in schema-version 1.2.0."
193
+ },
194
+ "supersedes": {
195
+ "type": "string",
196
+ "description": "The previous fact id/version this one supersedes."
197
+ }
198
+ }
199
+ },
200
+ "Source": {
201
+ "type": "object",
202
+ "additionalProperties": false,
203
+ "required": ["kind", "freshness", "refresh"],
204
+ "description": "External source of a Kind-B (cached-view) fact. Added in schema-version 1.1.0. Absent for Kind-A (immutable historical) facts.",
205
+ "properties": {
206
+ "kind": {
207
+ "type": "string",
208
+ "enum": ["http-api", "blob", "mcp-tool", "external-db", "user-input"],
209
+ "description": "Where the source of truth lives. Opaque to the memory layer; the `refresh.handler` knows how to fetch from it."
210
+ },
211
+ "uri": {
212
+ "type": "string",
213
+ "description": "Optional locator interpreted per `kind` (URL, blob ref, MCP tool id + args, JDBC URI, etc.). May be absent when the handler resolves the source internally."
214
+ },
215
+ "freshness": {
216
+ "type": "object",
217
+ "additionalProperties": false,
218
+ "description": "How to tell if the cached fact is still current.",
219
+ "properties": {
220
+ "ttlSeconds": {
221
+ "type": "integer",
222
+ "minimum": 0,
223
+ "description": "Fact is considered stale after this many seconds past `lastVerifiedAt`."
224
+ },
225
+ "lastVerifiedAt": {
226
+ "type": "string",
227
+ "format": "date-time",
228
+ "description": "When the source was last confirmed to still match the cached value. Updated by refresh handlers."
229
+ },
230
+ "etag": {
231
+ "type": "string",
232
+ "description": "HTTP-style validator, if the source supports one. Refresh handlers use conditional GET semantics."
233
+ },
234
+ "sourceVersion": {
235
+ "type": "string",
236
+ "description": "Explicit source-side version identifier (e.g., document revision id, DB row transaction id). Present when the source is versioned."
237
+ }
238
+ }
239
+ },
240
+ "refresh": {
241
+ "type": "object",
242
+ "additionalProperties": false,
243
+ "required": ["strategy"],
244
+ "description": "How the cached fact gets refreshed.",
245
+ "properties": {
246
+ "strategy": {
247
+ "type": "string",
248
+ "enum": ["on-read", "background", "manual"],
249
+ "description": "'on-read' = reader triggers a refresh check before returning stale results. 'background' = a scheduled kernel run walks stale facts and refreshes. 'manual' = only refresh when explicitly invoked."
250
+ },
251
+ "handler": {
252
+ "type": "string",
253
+ "description": "Tool id, agent id, or flow id that performs the refresh. Invoked by the kernel per the chosen strategy."
254
+ },
255
+ "priority": {
256
+ "type": "integer",
257
+ "description": "Higher = refresh first when a background sweep dispatches many at once."
258
+ }
259
+ }
260
+ }
261
+ }
262
+ },
263
+ "Retention": {
264
+ "type": "object",
265
+ "additionalProperties": false,
266
+ "description": "Fact-level retention override. Tenant policy sets defaults.",
267
+ "properties": {
268
+ "keepUntil": {
269
+ "type": "string",
270
+ "format": "date-time"
271
+ },
272
+ "keepDays": {
273
+ "type": "integer",
274
+ "minimum": 0
275
+ },
276
+ "legalHold": {
277
+ "type": "boolean",
278
+ "description": "If true, retention rules cannot delete this fact. Requires explicit release via admin action."
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }