@cleocode/lafs 1.8.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -0
  3. package/dist/schemas/v1/conformance-profiles.json +39 -0
  4. package/dist/schemas/v1/envelope.schema.json +306 -0
  5. package/dist/schemas/v1/error-registry.json +162 -0
  6. package/dist/src/a2a/bindings/grpc.d.ts +67 -0
  7. package/dist/src/a2a/bindings/grpc.js +148 -0
  8. package/dist/src/a2a/bindings/http.d.ts +102 -0
  9. package/dist/src/a2a/bindings/http.js +120 -0
  10. package/dist/src/a2a/bindings/index.d.ts +35 -0
  11. package/dist/src/a2a/bindings/index.js +79 -0
  12. package/dist/src/a2a/bindings/jsonrpc.d.ts +77 -0
  13. package/dist/src/a2a/bindings/jsonrpc.js +114 -0
  14. package/dist/src/a2a/bridge.d.ts +175 -0
  15. package/dist/src/a2a/bridge.js +286 -0
  16. package/dist/src/a2a/extensions.d.ts +121 -0
  17. package/dist/src/a2a/extensions.js +205 -0
  18. package/dist/src/a2a/index.d.ts +40 -0
  19. package/dist/src/a2a/index.js +76 -0
  20. package/dist/src/a2a/streaming.d.ts +74 -0
  21. package/dist/src/a2a/streaming.js +265 -0
  22. package/dist/src/a2a/task-lifecycle.d.ts +109 -0
  23. package/dist/src/a2a/task-lifecycle.js +313 -0
  24. package/dist/src/budgetEnforcement.d.ts +84 -0
  25. package/dist/src/budgetEnforcement.js +328 -0
  26. package/dist/src/circuit-breaker/index.d.ts +121 -0
  27. package/dist/src/circuit-breaker/index.js +249 -0
  28. package/dist/src/cli.d.ts +16 -0
  29. package/dist/src/cli.js +63 -0
  30. package/dist/src/compliance.d.ts +31 -0
  31. package/dist/src/compliance.js +89 -0
  32. package/dist/src/conformance.d.ts +7 -0
  33. package/dist/src/conformance.js +248 -0
  34. package/dist/src/conformanceProfiles.d.ts +11 -0
  35. package/dist/src/conformanceProfiles.js +34 -0
  36. package/dist/src/deprecationRegistry.d.ts +13 -0
  37. package/dist/src/deprecationRegistry.js +39 -0
  38. package/dist/src/discovery.d.ts +286 -0
  39. package/dist/src/discovery.js +350 -0
  40. package/dist/src/envelope.d.ts +60 -0
  41. package/dist/src/envelope.js +136 -0
  42. package/dist/src/errorRegistry.d.ts +28 -0
  43. package/dist/src/errorRegistry.js +36 -0
  44. package/dist/src/fieldExtraction.d.ts +67 -0
  45. package/dist/src/fieldExtraction.js +133 -0
  46. package/dist/src/flagResolver.d.ts +46 -0
  47. package/dist/src/flagResolver.js +47 -0
  48. package/dist/src/flagSemantics.d.ts +16 -0
  49. package/dist/src/flagSemantics.js +45 -0
  50. package/dist/src/health/index.d.ts +105 -0
  51. package/dist/src/health/index.js +220 -0
  52. package/dist/src/index.d.ts +24 -0
  53. package/dist/src/index.js +34 -0
  54. package/dist/src/mcpAdapter.d.ts +28 -0
  55. package/dist/src/mcpAdapter.js +281 -0
  56. package/dist/src/mviProjection.d.ts +19 -0
  57. package/dist/src/mviProjection.js +116 -0
  58. package/dist/src/problemDetails.d.ts +34 -0
  59. package/dist/src/problemDetails.js +45 -0
  60. package/dist/src/shutdown/index.d.ts +69 -0
  61. package/dist/src/shutdown/index.js +160 -0
  62. package/dist/src/tokenEstimator.d.ts +87 -0
  63. package/dist/src/tokenEstimator.js +238 -0
  64. package/dist/src/types.d.ts +135 -0
  65. package/dist/src/types.js +12 -0
  66. package/dist/src/validateEnvelope.d.ts +15 -0
  67. package/dist/src/validateEnvelope.js +31 -0
  68. package/lafs.md +819 -0
  69. package/package.json +88 -0
  70. package/schemas/v1/agent-card.schema.json +230 -0
  71. package/schemas/v1/conformance-profiles.json +39 -0
  72. package/schemas/v1/context-ledger.schema.json +70 -0
  73. package/schemas/v1/discovery.schema.json +132 -0
  74. package/schemas/v1/envelope.schema.json +306 -0
  75. package/schemas/v1/error-registry.json +162 -0
package/lafs.md ADDED
@@ -0,0 +1,819 @@
1
+ # LAFS: LLM-Agent-First Specification
2
+
3
+ > 📚 **Documentation:** https://codluv.gitbook.io/lafs/
4
+ > **Version:** 1.6.0 | **Status:** Production Ready
5
+
6
+ ## 1. Scope
7
+
8
+ LAFS is a **response envelope contract specification**. It defines the canonical shape of structured responses — success envelopes, error envelopes, pagination metadata, and context preservation — for software systems whose primary consumer is an LLM agent or AI-driven tool.
9
+
10
+ LAFS is **not** a protocol, framework, or runtime. It specifies **what** a conformant response looks like, not how that response is transported or generated. Implementations MAY deliver LAFS envelopes over HTTP, gRPC, CLI, SDK interfaces, message queues, or any other transport mechanism. LAFS is transport-agnostic and language-agnostic.
11
+
12
+ LAFS is designed to complement — not compete with — existing agent and tool-integration protocols. The Model Context Protocol (MCP) defines how LLM hosts discover and invoke tools; the Agent-to-Agent protocol (A2A) defines how autonomous agents communicate and delegate tasks. LAFS operates at a different layer: it standardizes the **response contract** that tools and agents SHOULD return, regardless of the protocol used to invoke them. An MCP tool server, an A2A agent, or a plain REST API MAY all return LAFS-conformant envelopes.
13
+
14
+ While LAFS is purpose-built for AI and LLM tool ecosystems — where deterministic, machine-parseable responses are critical — the specification is generally applicable to any API that benefits from structured, predictable response contracts.
15
+
16
+ ---
17
+
18
+ ## 2. Non-Goals
19
+
20
+ The following capabilities are intentionally outside the scope of LAFS. This section exists to prevent scope creep and to clarify boundaries with complementary protocols.
21
+
22
+ 1. **Streaming responses.** LAFS defines discrete request/response envelopes. Streaming mechanisms such as SSE or WebSocket are transport concerns and MUST NOT be defined by LAFS.
23
+
24
+ 2. **Asynchronous processing.** LAFS envelopes are synchronous response contracts. Async job patterns (polling, webhooks, callback queues) are application-layer concerns and are outside LAFS scope.
25
+
26
+ 3. **Authentication and authorization.** LAFS is transport-agnostic; auth is a transport or middleware concern. LAFS MAY carry auth-related error codes (e.g., `E_AUTH_*`) but MUST NOT define authentication or authorization flows.
27
+
28
+ 4. **Multi-modal content.** LAFS envelopes carry structured JSON data. Binary payloads, media content negotiation, and multi-modal encoding are outside scope.
29
+
30
+ 5. **Transport binding.** LAFS defines the response envelope shape, not how it maps to HTTP status codes, gRPC metadata, or other transport semantics. Transport mapping specifications are a separate concern.
31
+
32
+ 6. **Service discovery.** LAFS does not define how consumers locate or enumerate LAFS-conformant endpoints. Discovery mechanisms SHOULD be provided by the deployment layer or complementary protocols.
33
+
34
+ ---
35
+
36
+ ## 3. RFC 2119 Keywords
37
+
38
+ The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are interpreted per RFC 2119.
39
+
40
+ ---
41
+
42
+ ## 4. Non-Negotiable Protocol Rules
43
+
44
+ 1. Output default MUST be machine-readable JSON.
45
+ 2. Human-readable mode MUST be explicit opt-in.
46
+ 3. Context continuity MUST be preserved across steps.
47
+ 4. MVI (Minimal Viable Information) MUST be default response behavior.
48
+ 5. Progressive disclosure MUST be used for expanded detail retrieval.
49
+ 6. Contracts MUST be deterministic and testable.
50
+
51
+ ---
52
+
53
+ ## 5. Format Semantics
54
+
55
+ ### 5.1 Required output semantics
56
+
57
+ - Default format MUST be `json`.
58
+ - `--human` MUST switch output mode to human-readable.
59
+ - `--json` MAY be supported as explicit alias/override and is RECOMMENDED.
60
+ - Providing both `--human` and `--json` MUST fail with `E_FORMAT_CONFLICT`.
61
+ - Explicit flags MUST override env/config defaults.
62
+
63
+ ### 5.2 Recommended precedence
64
+
65
+ 1. Explicit CLI/API request value
66
+ 2. Project config
67
+ 3. Global/user config
68
+ 4. Protocol default (`json`)
69
+
70
+ ### 5.3 Supported formats
71
+
72
+ LAFS supports exactly two output formats:
73
+
74
+ - **`json`** (default) — Machine-readable JSON envelope for programmatic consumption
75
+ - **`human`** — Human-readable text output for terminal display
76
+
77
+ #### 5.3.1 Human format definition
78
+
79
+ The `human` format produces plain text output optimized for terminal display:
80
+
81
+ - Suitable for direct human consumption in CLI environments
82
+ - NOT markdown, NOT tables, NOT structured data
83
+ - May include ANSI colors (respect `NO_COLOR` environment variable)
84
+ - Example: Tabular data displayed with aligned columns using spaces
85
+
86
+ ```
87
+ ID Name Status
88
+ ---- ------------ --------
89
+ 123 Alpha active
90
+ 456 Beta pending
91
+ ```
92
+
93
+ #### 5.3.2 Rejected formats
94
+
95
+ The following formats were explicitly rejected to maintain protocol minimalism:
96
+
97
+ | Format | Status | Rationale |
98
+ |--------|--------|-----------|
99
+ | `text` | ❌ Rejected | Ambiguous overlap with `human`. Use `human` format with `NO_COLOR=1` for plain text. |
100
+ | `markdown` | ❌ Rejected | Presentation format, not data format. Generate from JSON if markdown rendering is needed. |
101
+ | `table` | ❌ Rejected | Presentation concern. Use `jq` + `column` command or `human` format for tabular display. |
102
+ | `jsonl` | ❌ Rejected | Streaming format violates LAFS discrete envelope contract (see Section 2: Non-Goals). |
103
+
104
+ **Design principle:** LAFS is a response envelope contract, not a presentation layer. Six formats = format proliferation = protocol bloat.
105
+
106
+ #### 5.3.3 Achieving presentation goals with json format
107
+
108
+ Consumers needing presentation formats should:
109
+
110
+ 1. Request `json` format from LAFS-compliant services
111
+ 2. Transform JSON to desired presentation format using standard tools:
112
+ - **Markdown:** `jq` + template engine
113
+ - **Tables:** `jq` + `column` command
114
+ - **Plain text:** `jq` with `-r` (raw) output
115
+
116
+ ### 5.4 Cross-layer flag interaction
117
+
118
+ Flags operate on two independent layers: **format** (`--human`, `--json`, `--quiet`) and **field extraction** (`--field`, `--fields`, `--mvi`). When flags from both layers are combined, the following semantics apply:
119
+
120
+ #### 5.4.1 Filter-then-render (default)
121
+
122
+ When `--field` or `--fields` are combined with a format flag, the field extraction layer applies **first**, followed by the format layer:
123
+
124
+ - **`--human + --field`**: Extract the named field from the result, then render the extracted value in human-readable format. Implementations SHOULD emit a warning but MUST NOT error.
125
+ - **`--human + --fields`**: Filter result keys, then render the filtered result in human-readable format. Same warning behavior.
126
+ - **`--json + --field`**: Extract the named field and output as plain text (no envelope). This is the default behavior (no cross-layer concern).
127
+ - **`--json + --fields`**: Filter result keys within the JSON envelope. This is the default behavior.
128
+ - **`--quiet + --field`**: Valid combination. Extract field, output plain text.
129
+ - **`--quiet + --fields`**: Valid combination. Filter keys, output minimal.
130
+
131
+ #### 5.4.2 Error conditions
132
+
133
+ Cross-layer combinations that involve conflicting format flags still error per §5.1:
134
+
135
+ - **`--human + --json + --field`**: MUST fail with `E_FORMAT_CONFLICT` (format layer conflict, §5.1).
136
+ - **`--field + --fields`**: MUST fail with `E_FIELD_CONFLICT` (field layer conflict, §9.2).
137
+
138
+ #### 5.4.3 MVI interaction
139
+
140
+ - **`--human + --mvi`**: The `--mvi` level MAY be honored for metadata filtering; human rendering is the primary output format. No error or warning.
141
+
142
+ ---
143
+
144
+ ## 6. Canonical Response Envelope
145
+
146
+ All responses MUST conform to `schemas/v1/envelope.schema.json`.
147
+
148
+ ```json
149
+ {
150
+ "$schema": "https://lafs.dev/schemas/v1/envelope.schema.json",
151
+ "_meta": {
152
+ "specVersion": "1.0.0",
153
+ "schemaVersion": "1.0.0",
154
+ "timestamp": "2026-02-11T00:00:00Z",
155
+ "operation": "operation.name",
156
+ "requestId": "req_123",
157
+ "transport": "cli",
158
+ "strict": true,
159
+ "mvi": "standard",
160
+ "contextVersion": 0
161
+ },
162
+ "success": true,
163
+ "result": {},
164
+ "error": null,
165
+ "page": null
166
+ }
167
+ ```
168
+
169
+ ### 6.1 Envelope invariants
170
+
171
+ - `success=true` implies `error=null` or error omitted.
172
+ - `success=false` implies `result=null` and `error` MUST be present.
173
+ - The `page` and `error` fields are optional when their value would be null. In strict mode, producers SHOULD omit these fields rather than set them to null.
174
+ - Unknown fields SHOULD be rejected when strict mode is enabled.
175
+
176
+ ### 6.2 Extensions
177
+
178
+ The envelope supports an optional `_extensions` object for vendor-specific metadata. Because `_extensions` is a declared property in the schema, it is permitted regardless of strict mode.
179
+
180
+ - Keys SHOULD use the `x-` prefix convention (e.g., `x-myvendor-trace-id`).
181
+ - Consumers MUST NOT rely on extension fields for protocol-required behavior.
182
+ - Producers MAY omit `_extensions` entirely; the field is always optional.
183
+
184
+ #### 6.2.1 Extension use cases
185
+
186
+ The following examples demonstrate common use cases for `_extensions`. These fields were rejected from the core protocol but are valid extension use cases.
187
+
188
+ **Example 1: Performance timing**
189
+
190
+ ```typescript
191
+ // Extension type definition
192
+ interface XTimingExtension {
193
+ "x-timing": {
194
+ executionMs: number; // Total request execution time
195
+ parseMs?: number; // Input parsing time
196
+ queryMs?: number; // Database query time
197
+ serializeMs?: number; // Response serialization time
198
+ };
199
+ }
200
+ ```
201
+
202
+ ```json
203
+ {
204
+ "_extensions": {
205
+ "x-timing": {
206
+ "executionMs": 42,
207
+ "queryMs": 15,
208
+ "serializeMs": 3
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ **Example 2: Source metadata**
215
+
216
+ ```typescript
217
+ interface XSourceExtension {
218
+ "x-source": {
219
+ gitRef?: string; // Git commit SHA
220
+ apiVersion?: string; // API implementation version
221
+ buildTimestamp?: string; // ISO 8601 build time
222
+ deployment?: string; // Deployment environment (staging, prod)
223
+ };
224
+ }
225
+ ```
226
+
227
+ ```json
228
+ {
229
+ "_extensions": {
230
+ "x-source": {
231
+ "gitRef": "abc123def456",
232
+ "apiVersion": "2.1.0",
233
+ "deployment": "production"
234
+ }
235
+ }
236
+ }
237
+ ```
238
+
239
+ **Example 3: Applied filters**
240
+
241
+ ```typescript
242
+ interface XFiltersExtension {
243
+ "x-filters": {
244
+ applied: Array<{
245
+ field: string;
246
+ operator: "eq" | "neq" | "gt" | "lt" | "contains";
247
+ value: unknown;
248
+ }>;
249
+ omitted: string[]; // Fields excluded due to permissions
250
+ };
251
+ }
252
+ ```
253
+
254
+ ```json
255
+ {
256
+ "_extensions": {
257
+ "x-filters": {
258
+ "applied": [
259
+ { "field": "status", "operator": "eq", "value": "active" },
260
+ { "field": "createdAt", "operator": "gt", "value": "2024-01-01" }
261
+ ],
262
+ "omitted": ["internalNotes", "costCenter"]
263
+ }
264
+ }
265
+ }
266
+ ```
267
+
268
+ **Example 4: Result summary**
269
+
270
+ ```typescript
271
+ interface XSummaryExtension {
272
+ "x-summary": {
273
+ totalCount: number; // Total matching records
274
+ returnedCount: number; // Records in this response
275
+ aggregated?: {
276
+ revenue?: number;
277
+ count?: number;
278
+ average?: number;
279
+ };
280
+ };
281
+ }
282
+ ```
283
+
284
+ ```json
285
+ {
286
+ "_extensions": {
287
+ "x-summary": {
288
+ "totalCount": 150,
289
+ "returnedCount": 25,
290
+ "aggregated": {
291
+ "revenue": 125000.00,
292
+ "average": 833.33
293
+ }
294
+ }
295
+ }
296
+ }
297
+ ```
298
+
299
+ #### 6.2.2 Extension best practices
300
+
301
+ 1. **Use x- prefix** — All extension keys MUST start with `x-` (e.g., `x-caamp-timing`)
302
+ 2. **Document your schema** — Publish extension schemas separately from LAFS core
303
+ 3. **Don't rely on extensions for core behavior** — Extensions are informational only
304
+ 4. **Version your extensions** — Include version in extension key if schema may change (e.g., `x-vendor-v2-field`)
305
+ 5. **Keep extensions optional** — Consumers MUST be able to operate without extension data
306
+ 6. **Namespace by vendor** — Use vendor prefix to avoid collisions (e.g., `x-caamp-`, `x-acme-`)
307
+
308
+ #### 6.2.3 When to use extensions vs core protocol
309
+
310
+ | Use Case | Core Protocol | Extensions |
311
+ |----------|---------------|------------|
312
+ | Session correlation | ✅ sessionId | — |
313
+ | Soft warnings | ✅ warnings array | — |
314
+ | Performance timing | — | ✅ x-timing |
315
+ | Source/version metadata | — | ✅ x-source |
316
+ | Debug filters | — | ✅ x-filters |
317
+ | Derived summaries | — | ✅ x-summary |
318
+ | Data integrity (TLS covers) | — | ✅ x-checksum (if needed) |
319
+
320
+ **Guideline:** If a field is required for basic operation, it belongs in core. If it's useful for debugging, monitoring, or rich display, it belongs in extensions.
321
+
322
+ ---
323
+
324
+ ## 7. Error Contract
325
+
326
+ Errors MUST conform to envelope `error` shape and use codes from `schemas/v1/error-registry.json`.
327
+
328
+ ```json
329
+ {
330
+ "code": "E_VALIDATION_SCHEMA",
331
+ "message": "Invalid input payload",
332
+ "category": "VALIDATION",
333
+ "retryable": false,
334
+ "retryAfterMs": null,
335
+ "details": {
336
+ "field": "limit"
337
+ }
338
+ }
339
+ ```
340
+
341
+ ### 7.1 Error code naming convention
342
+
343
+ Error codes MUST match the pattern: `^E_[A-Z0-9]+_[A-Z0-9_]+$`
344
+
345
+ The structure is **E\_\<DOMAIN\>\_\<SPECIFIC\>**, where:
346
+
347
+ - **E\_** — required prefix identifying the value as an error code.
348
+ - **DOMAIN** — a short uppercase token describing the error's semantic area (e.g., `VALIDATION`, `CONTEXT`, `RATE`, `MIGRATION`). The domain is descriptive; it does not need to equal the `category` enum value.
349
+ - **SPECIFIC** — one or more uppercase tokens (separated by `_`) that distinguish the error within its domain (e.g., `SCHEMA`, `MISSING`, `UNSUPPORTED_VERSION`).
350
+
351
+ Examples from the registry:
352
+
353
+ | Code | Domain | Specific | Category |
354
+ |---|---|---|---|
355
+ | `E_VALIDATION_SCHEMA` | `VALIDATION` | `SCHEMA` | VALIDATION |
356
+ | `E_NOT_FOUND_RESOURCE` | `NOT` | `FOUND_RESOURCE` | NOT_FOUND |
357
+ | `E_CONTEXT_MISSING` | `CONTEXT` | `MISSING` | CONTRACT |
358
+ | `E_MIGRATION_UNSUPPORTED_VERSION` | `MIGRATION` | `UNSUPPORTED_VERSION` | MIGRATION |
359
+
360
+ Registered categories (the `category` field in error objects): `VALIDATION`, `AUTH`, `PERMISSION`, `NOT_FOUND`, `CONFLICT`, `RATE_LIMIT`, `TRANSIENT`, `INTERNAL`, `CONTRACT`, `MIGRATION`.
361
+
362
+ Custom error codes MUST match the same regex pattern. Implementations SHOULD choose a domain token that clearly communicates the error's origin.
363
+
364
+ ### 7.2 Required behavior
365
+
366
+ - Error codes MUST be stable within major versions.
367
+ - Retry semantics MUST be encoded in `retryable` and `retryAfterMs`.
368
+ - CLI/HTTP/gRPC mappings SHOULD follow the registry.
369
+
370
+ ### 7.3 Agent action semantics
371
+
372
+ Error objects MAY include an `agentAction` field providing a machine-readable
373
+ instruction for the consuming agent. When present, `agentAction` MUST be one of:
374
+
375
+ | Value | Semantics |
376
+ |-------|-----------|
377
+ | `retry` | Transient failure. Agent SHOULD retry the same request, optionally after `retryAfterMs`. |
378
+ | `retry_modified` | Request was invalid. Agent SHOULD modify request parameters and retry. The `details` field SHOULD indicate which parameters to change. |
379
+ | `wait` | Rate limited. Agent MUST wait at least `retryAfterMs` milliseconds before retrying. Exponential backoff is RECOMMENDED. |
380
+ | `escalate` | Requires human or operator intervention. Agent SHOULD surface the error to the user with the `requestId` for correlation. |
381
+ | `stop` | Terminal error. Agent MUST NOT retry this request. |
382
+ | `refresh_context` | Context is stale. Agent SHOULD fetch fresh context via `contextVersion` and retry. |
383
+ | `authenticate` | Authentication required or expired. Agent SHOULD obtain or refresh credentials before retrying. |
384
+
385
+ When `agentAction` is absent, agents SHOULD derive the action from `category`
386
+ using the default mapping published in the error registry.
387
+
388
+ Implementations SHOULD always include `agentAction` in error responses to
389
+ eliminate ambiguity and reduce agent reasoning overhead.
390
+
391
+ #### 7.3.1 Escalation signal
392
+
393
+ Error objects MAY include an `escalationRequired` boolean field. When `true`,
394
+ the agent MUST NOT attempt automated recovery and SHOULD surface the error
395
+ to a human operator. This field is independent of `retryable`: an error may
396
+ be retryable by a human but not by an agent.
397
+
398
+ #### 7.3.2 Suggested action
399
+
400
+ Error objects MAY include a `suggestedAction` string field providing a brief,
401
+ specific instruction for recovery. This field is distinct from `message` (which
402
+ describes what happened) and carries actionable guidance for the consumer.
403
+
404
+ #### 7.3.3 Documentation URL
405
+
406
+ Error objects MAY include a `docUrl` string field containing a URI pointing to
407
+ documentation for the error type. Agents capable of web retrieval MAY use this
408
+ for autonomous error resolution. The error registry SHOULD publish `docUrl`
409
+ values for all registered error codes.
410
+
411
+ ---
412
+
413
+ ## 8. Context Preservation
414
+
415
+ Multi-step operations MUST preserve a context ledger with at least:
416
+
417
+ - `objective`
418
+ - `constraints[]`
419
+ - `references[]`
420
+ - `decisions[]`
421
+ - `openIssues[]`
422
+ - `state`
423
+ - `version`
424
+
425
+ Rules:
426
+
427
+ - Version MUST increase monotonically by 1 for accepted mutations.
428
+ - Accepted active constraints MUST NOT be silently removed.
429
+ - Decisions affecting output MUST be represented in ledger state.
430
+ - Missing required context for a mutating step MUST fail with structured error.
431
+
432
+ ### 8.1 Context Retrieval
433
+
434
+ Agents MAY retrieve context ledger state via `GET /_lafs/context/{ledgerId}` with projection modes.
435
+
436
+ #### 8.1.1 Projection Modes
437
+
438
+ **Full Mode (`mode=full`):**
439
+ Returns complete ledger including all entries.
440
+ - Use for: Initial loads, recovery scenarios
441
+ - Supports: Offset-based pagination
442
+ - Response includes: All ledger fields
443
+
444
+ **Delta Mode (`mode=delta&sinceVersion=N`):**
445
+ Returns only entries added since version N.
446
+ - Use for: Active workflows (efficient sync)
447
+ - Response includes:
448
+ ```json
449
+ {
450
+ "ledgerId": "ctx_abc123",
451
+ "mode": "delta",
452
+ "fromVersion": 10,
453
+ "toVersion": 15,
454
+ "entries": [/* new entries only */],
455
+ "removedConstraints": [/* constraints no longer active */],
456
+ "checksum": "sha256:..."
457
+ }
458
+ ```
459
+
460
+ **Summary Mode (`mode=summary`):**
461
+ Returns checksum and version for validation.
462
+ - Use for: Quick sync validation
463
+ - Response includes only: `ledgerId`, `version`, `checksum`, `entryCount`
464
+
465
+ #### 8.1.2 Query Parameters
466
+
467
+ | Parameter | Type | Description |
468
+ |-----------|------|-------------|
469
+ | `mode` | enum | `full`, `delta`, `summary` |
470
+ | `sinceVersion` | integer | For delta mode: return entries after this version |
471
+ | `filterByOperation` | string[] | Filter entries by operation name(s) |
472
+ | `limit` | integer | Max entries (1-1000, default 100) |
473
+ | `includeChecksum` | boolean | Include integrity checksum (default true) |
474
+
475
+ #### 8.1.3 Agent Guidance
476
+
477
+ - **Initial load**: Use `mode=full` once
478
+ - **Active workflows**: Use `mode=delta` with last known version
479
+ - **Validation**: Use `mode=summary` to verify sync state
480
+ - **Default recommendation**: `delta` mode for agent-optimal behavior
481
+
482
+ ### 8.2 Lazy Context Retrieval
483
+
484
+ To reduce token and I/O overhead, implementations SHOULD support lazy retrieval semantics:
485
+
486
+ - Clients SHOULD start with `mode=summary` and request `mode=delta` only when `version` or `checksum` changes.
487
+ - Delta responses SHOULD be bounded by `limit` and MAY return paged deltas.
488
+ - Servers SHOULD treat context retrieval as task-scoped and MUST NOT leak entries across `contextId` domains.
489
+ - When a consumer requests additional context beyond MVI defaults, servers MAY return progressive context slices rather than full ledgers.
490
+ - If requested context scope cannot be satisfied within declared budget, servers SHOULD fail with `E_MVI_BUDGET_EXCEEDED`.
491
+
492
+ ---
493
+
494
+ ## 9. MVI and Progressive Disclosure
495
+
496
+ ### 9.1 MVI default
497
+
498
+ - Default list/batch outputs MUST only contain fields required for next action.
499
+ - Verbose fields SHOULD be omitted by default.
500
+ - Systems SHOULD publish operation-level MVI budgets.
501
+ - `_meta.mvi` MUST be one of: `minimal`, `standard`, `full`, or `custom`.
502
+ - `_meta` MUST always be present as a structural envelope field. `success` MUST
503
+ always be present. `error` MUST be present when `success` is `false`.
504
+ - MVI levels govern the verbosity of `result`, `_meta` fields, and `error` fields.
505
+ At `minimal`, implementations SHOULD omit fields that are derivable from the
506
+ error registry or that echo back request parameters the agent already knows.
507
+ - The following envelope structural invariants are NOT affected by MVI level:
508
+ the mutual exclusivity of `result` and `error`, the presence of `success`,
509
+ and the presence of `_meta`.
510
+ - `minimal`: MUST include only fields within `result` sufficient for the next
511
+ agent action (typically identifiers and status). Implementations SHOULD
512
+ document which fields constitute `minimal` per operation.
513
+ - `standard` (default): MUST include all commonly useful fields for the
514
+ operation.
515
+ - `full`: MUST include all available fields including verbose and
516
+ rarely-accessed data.
517
+ - `custom`: MUST be set by the server when `_fields` projection has been
518
+ applied, indicating the result does not conform to any predefined disclosure
519
+ level. `custom` is not a client-requestable level.
520
+
521
+ #### 9.1.1 MVI field inclusion for `_meta`
522
+
523
+ At `minimal`, `_meta` MUST include only:
524
+ - `requestId` (REQUIRED)
525
+ - `contextVersion` (REQUIRED)
526
+ - `sessionId` (REQUIRED when present in the full response)
527
+ - `warnings` (REQUIRED when present in the full response)
528
+
529
+ At `standard`, `_meta` MUST additionally include:
530
+ - `timestamp`
531
+ - `operation`
532
+ - `mvi`
533
+
534
+ At `full`, `_meta` MUST include all defined fields including `specVersion`,
535
+ `schemaVersion`, `transport`, and `strict`.
536
+
537
+ Fields omitted at a given MVI level are echo-backs of request parameters that
538
+ the agent already knows, or static constants that do not vary per response.
539
+
540
+ #### 9.1.2 MVI field inclusion for `error`
541
+
542
+ At `minimal`, `error` MUST include only:
543
+ - `code` (REQUIRED)
544
+ - `agentAction` (REQUIRED when present)
545
+ - `retryAfterMs` (REQUIRED when non-null)
546
+ - `details` (REQUIRED when non-empty)
547
+ - `escalationRequired` (REQUIRED when present)
548
+
549
+ At `standard` and `full`, `error` MUST include all fields defined in Section 7,
550
+ including `message`, `category`, `retryable`, and `retryAfterMs`.
551
+
552
+ Fields omitted at `minimal` are either human-readable prose (`message`) or
553
+ derivable from the error code via the error registry (`category`, `retryable`).
554
+
555
+ #### 9.1.3 MVI field inclusion for envelope structure
556
+
557
+ At `minimal`:
558
+ - `$schema` MAY be omitted (static constant)
559
+ - `result` MAY be omitted when its value is `null` (derivable from `success: false`)
560
+
561
+ At `standard` and `full`, all structural fields MUST be present per the
562
+ envelope schema.
563
+
564
+ ### 9.2 Field selection (`_fields`)
565
+
566
+ Clients MAY request a subset of response fields via the `_fields` request
567
+ parameter.
568
+
569
+ - `_fields` MUST be an array of strings identifying `result` field names.
570
+ Path notation (e.g., `task.title`) is not defined by this specification.
571
+ - When `result` is an array, `_fields` applies to the keys of each element.
572
+ - When `result` is a wrapper object whose values are entities or arrays of
573
+ entities (e.g., `{ "task": { ... } }` or `{ "items": [...] }`), servers
574
+ SHOULD apply `_fields` to the nested entity fields rather than the wrapper's
575
+ own keys.
576
+ - When `_fields` is present, the server MUST return only the requested fields
577
+ plus any MVI-required fields for the declared disclosure level.
578
+ The server MUST set `_meta.mvi` to `custom` in the response.
579
+ - When `_fields` is absent, the server MUST return fields appropriate for the
580
+ declared `_meta.mvi` disclosure level.
581
+ - If a requested field does not exist on the resource, the server SHOULD omit
582
+ it silently (no error). Servers MAY include a warning in `_meta.warnings`
583
+ for unknown fields.
584
+ - `_fields` MUST NOT affect envelope structural fields (`$schema`, `_meta`,
585
+ `success`, `error`, `page`, `_extensions`); it applies only to the contents
586
+ of `result`.
587
+
588
+ ### 9.3 Expansion mechanism (`_expand`)
589
+
590
+ Clients MAY request expanded/nested data via the `_expand` request parameter.
591
+
592
+ - `_expand` MUST be an array of strings identifying relationships or nested resources to include inline.
593
+ - When `_expand` is present, the server MUST resolve and inline the requested expansions within `result`.
594
+ - If a requested expansion field is not recognized, the server MUST return error code `E_DISCLOSURE_UNKNOWN_FIELD` with category `VALIDATION`.
595
+ - Servers SHOULD document available expansion fields per operation.
596
+ - Expansion depth MUST be limited to prevent unbounded recursion. Servers SHOULD enforce a maximum expansion depth and return `E_MVI_BUDGET_EXCEEDED` if exceeded.
597
+
598
+ ### 9.4 Pagination
599
+
600
+ - List operations SHOULD return deterministic `page` metadata.
601
+ - Pagination mode (offset or cursor) MUST be documented.
602
+ - Mixed pagination modes in one request MUST fail validation.
603
+ - `page.limit` SHOULD represent the effective item window after `_fields`/`_expand` processing.
604
+ - When `_meta.mvi` is `minimal` and projected payload size exceeds budget, servers SHOULD reduce `page.limit` rather than silently truncate item content.
605
+ - If limit reduction still cannot satisfy declared budget, servers MUST fail with `E_MVI_BUDGET_EXCEEDED`.
606
+
607
+ ### 9.5 Token Budget Signaling
608
+
609
+ Token budget signaling enables clients to declare resource constraints that servers MUST respect when generating responses. This mechanism prevents context window overflow in LLM-driven workflows.
610
+
611
+ #### 9.5.1 Budget Declaration (`_budget`)
612
+
613
+ Clients MAY declare resource constraints via the `_budget` request parameter:
614
+
615
+ ```json
616
+ {
617
+ "_budget": {
618
+ "maxTokens": 4000,
619
+ "maxBytes": 32768,
620
+ "maxItems": 100
621
+ }
622
+ }
623
+ ```
624
+
625
+ **Fields:**
626
+ - `maxTokens` (integer) - Maximum approximate tokens
627
+ - `maxBytes` (integer) - Maximum byte size
628
+ - `maxItems` (integer) - Maximum items in lists
629
+
630
+ **Constraints:**
631
+ - At least one field MUST be present
632
+ - All values MUST be positive integers
633
+ - Servers MAY reject budgets exceeding implementation limits
634
+
635
+ #### 9.5.2 Server Behavior
636
+
637
+ Servers MUST:
638
+ 1. Parse `_budget` from incoming requests
639
+ 2. Estimate/measure response size
640
+ 3. Return response within budget OR fail with `E_MVI_BUDGET_EXCEEDED`
641
+
642
+ Servers MAY truncate responses using:
643
+ - **Depth-first**: Remove deepest nested fields
644
+ - **Field priority**: Remove non-essential fields first
645
+ - **Hybrid**: Combine both strategies
646
+
647
+ When truncation occurs, servers MUST include:
648
+ ```json
649
+ {
650
+ "_meta": {
651
+ "warnings": [{
652
+ "code": "E_MVI_BUDGET_TRUNCATED",
653
+ "message": "Response truncated to fit token budget"
654
+ }],
655
+ "_tokenEstimate": {
656
+ "estimated": 2847,
657
+ "budget": 4000,
658
+ "method": "character_based"
659
+ }
660
+ }
661
+ }
662
+ ```
663
+
664
+ #### 9.5.3 Error Specification
665
+
666
+ **E_MVI_BUDGET_EXCEEDED:**
667
+ - **Category:** `VALIDATION`
668
+ - **Retryable:** `true`
669
+ - **Details:** `estimatedTokens`, `budget`, `excessTokens`, `constraint`
670
+
671
+ ```json
672
+ {
673
+ "error": {
674
+ "code": "E_MVI_BUDGET_EXCEEDED",
675
+ "message": "Response exceeds declared token budget",
676
+ "category": "VALIDATION",
677
+ "retryable": true,
678
+ "details": {
679
+ "estimatedTokens": 5234,
680
+ "budget": 4000,
681
+ "excessTokens": 1234,
682
+ "constraint": "maxTokens"
683
+ }
684
+ }
685
+ }
686
+ ```
687
+
688
+ #### 9.5.4 Token Estimation Algorithm (Normative)
689
+
690
+ Servers MUST implement this algorithm or equivalent (within +/- 10%):
691
+
692
+ ```
693
+ FUNCTION estimate_tokens(value, depth = 0):
694
+ IF depth > 20: RETURN INFINITY
695
+ IF value IS null: RETURN 1
696
+ IF value IS boolean: RETURN 1
697
+ IF value IS number: RETURN max(1, len(stringify(value)) / 4)
698
+ IF value IS string:
699
+ graphemes = count_grapheme_clusters(value)
700
+ RETURN max(1, graphemes / 4.0)
701
+ IF value IS array:
702
+ tokens = 2 // []
703
+ FOR item IN value:
704
+ tokens += estimate_tokens(item, depth + 1) + 1
705
+ RETURN tokens
706
+ IF value IS object:
707
+ tokens = 2 // {}
708
+ FOR key, val IN value:
709
+ tokens += estimate_tokens(key, depth + 1)
710
+ tokens += 2 // : and ,
711
+ tokens += estimate_tokens(val, depth + 1)
712
+ RETURN tokens
713
+ ```
714
+
715
+ **Requirements:**
716
+ - Count grapheme clusters (not bytes) for unicode
717
+ - Enforce max depth of 20
718
+ - Handle circular references
719
+ - Complete within 10ms for 100KB payloads
720
+
721
+ ---
722
+
723
+ ## 10. Strictness
724
+
725
+ - Agent surfaces SHOULD default `strict=true`.
726
+ - Strict mode violations SHOULD fail with contract/validation error codes.
727
+ - Response metadata MUST expose strict mode status.
728
+
729
+ ---
730
+
731
+ ## 11. Versioning and Deprecation
732
+
733
+ - Protocol versions MUST follow SemVer.
734
+ - Minor/patch changes MUST be backward compatible.
735
+ - Breaking changes MUST require major version increments.
736
+ - Deprecated fields MUST have documented sunset policy.
737
+
738
+ See `docs/VERSIONING.md` and `docs/DEPRECATION.md`.
739
+
740
+ ---
741
+
742
+ ## 12. Conformance
743
+
744
+ Conforming implementations MUST pass minimum checks in `docs/CONFORMANCE.md` and schema validation for the canonical envelope.
745
+
746
+ ### 12.1 Adoption Tiers
747
+
748
+ LAFS defines three adoption tiers to enable gradual conformance. Each tier builds on the previous tier's requirements. Implementations MUST declare which tier they target and MUST pass all checks required by that tier.
749
+
750
+ #### 12.1.1 Core Tier
751
+
752
+ The Core tier represents **minimum viable LAFS adoption**. It verifies that responses use the canonical envelope shape and satisfy basic structural invariants.
753
+
754
+ Required conformance checks:
755
+
756
+ | Check | Description |
757
+ |---|---|
758
+ | `envelope_schema_valid` | Response validates against `schemas/v1/envelope.schema.json` |
759
+ | `envelope_invariants` | `success`/`result`/`error` mutual exclusivity holds (Section 6.1) |
760
+
761
+ Use cases: quick adoption, internal APIs, prototyping, evaluating LAFS fit.
762
+
763
+ #### 12.1.2 Standard Tier
764
+
765
+ The Standard tier is **recommended for production** use. It adds semantic checks for error codes, metadata flags, and format defaults on top of all Core tier requirements.
766
+
767
+ Required conformance checks — all Core checks, plus:
768
+
769
+ | Check | Description |
770
+ |---|---|
771
+ | `error_code_registered` | All error codes come from the registered error registry (Section 7) |
772
+ | `meta_mvi_present` | `_meta.mvi` flag is present and valid (Section 9.1) |
773
+ | `meta_strict_present` | `_meta.strict` flag is present and boolean (Section 10) |
774
+ | `json_protocol_default` | JSON is the default output format when no explicit format is requested (Section 5.1) |
775
+
776
+ Use cases: production APIs, public-facing services, third-party integrations.
777
+
778
+ #### 12.1.3 Complete Tier
779
+
780
+ The Complete tier represents **full LAFS compliance**. It adds configuration, flag-handling, and advanced feature checks on top of all Standard tier requirements.
781
+
782
+ Required conformance checks — all Standard checks, plus:
783
+
784
+ | Check | Description |
785
+ |---|---|
786
+ | `config_override_respected` | Project/user config-based format overrides are correctly applied (Section 5.2) |
787
+ | `flag_conflict_rejected` | Conflicting format flags (e.g., `--human --json`) are properly rejected with `E_FORMAT_CONFLICT` (Section 5.1) |
788
+ | `context_validation` | Context preservation invariants hold for multi-step operations (Section 8) |
789
+ | `pagination_validation` | Pagination metadata validates when present (Section 9.3) |
790
+
791
+ Use cases: official LAFS-conformant implementations, reference implementations, certification.
792
+
793
+ > **Note:** `context_validation` and `pagination_validation` are reserved check names. Implementations SHOULD treat these as automatically passing until the corresponding conformance runners are available.
794
+
795
+ ---
796
+
797
+ ## 13. Security Considerations
798
+
799
+ This section addresses security threats relevant to LAFS envelope production and consumption. LAFS is transport-agnostic and does not define its own cryptographic or authentication mechanisms; implementers MUST rely on the underlying transport and application layers for those controls.
800
+
801
+ ### 13.1 Injection attacks
802
+
803
+ LAFS envelopes carry user-provided data in `result`, `error`, and `details` fields. Implementers MUST sanitize all envelope contents before rendering in HTML, constructing shell commands, or executing in eval-like contexts. Error messages MUST NOT contain unsanitized user input. Implementations that embed envelope values in SQL, LDAP, or similar query languages MUST use parameterized interfaces.
804
+
805
+ ### 13.2 Tampering
806
+
807
+ LAFS does not define integrity protection at the envelope level. If envelope integrity is required, implementers SHOULD use transport-level security (e.g., TLS) and MAY implement envelope signing as an extension. Consumers MUST NOT trust envelope contents without verifying the transport channel. Implementations that relay envelopes across trust boundaries SHOULD re-validate against `schemas/v1/envelope.schema.json` at each boundary.
808
+
809
+ ### 13.3 Information disclosure
810
+
811
+ Error details MAY contain sensitive information such as stack traces, internal paths, or database identifiers. Implementations SHOULD distinguish between development and production error detail levels. The `details` field in error objects MUST NOT expose internal system information in production environments. Implementations SHOULD define an explicit allow-list of fields permitted in production error responses.
812
+
813
+ ### 13.4 Replay attacks
814
+
815
+ LAFS includes `requestId` and `timestamp` in `_meta` for correlation (Section 6). Implementers MAY use these fields for replay detection but MUST NOT rely solely on them, as LAFS does not mandate uniqueness or freshness guarantees for these values. Transport-level replay protection (e.g., TLS with appropriate session management) is RECOMMENDED.
816
+
817
+ ### 13.5 Denial of service
818
+
819
+ Large envelope payloads could be used for resource exhaustion. Implementations SHOULD enforce maximum envelope size limits appropriate to their deployment context. Pagination (Section 9.3) SHOULD be used to bound response sizes for list operations. Implementations SHOULD reject envelopes that exceed the configured size limit with a structured error.