compose-lens 0.3.0

Loss-aware parsing, processing, validation, and rendering of Compose projects
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# Roadmap

This roadmap orders ComposeLens work by consumer value and records the exact current specification
surface that is not yet available through a native typed API. It is not a delivery schedule.

The [quality plan](quality-plan.md) groups the remaining work into maintainable priorities and
defines what “good enough” means for testing and conformance.

## Coverage language

ComposeLens has several independent coverage layers:

| State                   | Meaning                                                                                                           |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Syntax-preserved        | The YAML parser retains the key, spelling, order, source range, extensions, and unknown fields where recoverable. |
| Document typed          | One authored document exposes a native source-aware value.                                                        |
| Project typed           | The effective merged/profile-selected project exposes the value with provenance.                                  |
| Generated               | New Compose YAML can be constructed through typed values and parse-back validation.                               |
| Compatibility-evidenced | Provider/runtime/version behavior is backed by documented or observed evidence.                                   |

“Not typed” does not mean “cannot be read.” Every key below remains available through the
loss-aware syntax document. It means callers cannot yet consume that key through a dedicated
ComposeLens semantic type.

## Specification snapshot

This ledger was audited on 2026-08-14 against the official
[Compose JSON schema snapshot](../schema/compose-spec.json) from
[compose-spec commit 11296e387ba76c77db1db768b9153a4304a3c9bd](https://github.com/compose-spec/compose-spec/blob/11296e387ba76c77db1db768b9153a4304a3c9bd/schema/compose-spec.json),
[Compose Specification](https://github.com/compose-spec/compose-spec/blob/main/spec.md), and
[Docker Compose file reference](https://docs.docker.com/reference/compose-file/).
Provider additions remain eligible when real Docker Compose or Podman Compose accepts them; the
compose-spec repository is not the sole compatibility authority.

The audited schema currently contains 9 top-level keys and 93 service keys.

| Surface   | Project typed | Document typed only | Syntax-preserved only |
| --------- | ------------: | ------------------: | --------------------: |
| Top level |             9 |                   0 |                     0 |
| Service   |            93 |                   0 |                     0 |

`x-*` extensions are intentionally open-ended and preserved. They are not counted as missing
closed-schema keys.

The closed root/service-key snapshot and its strict classification inventory are maintained in
[`schema/`](../schema/). Offline repository policy tests verify the pinned digest, the closed
`additionalProperties: false` shape, the sole `^x-` extension allowance, and exact 9/93 key sets.
Scheduled or manually dispatched upstream drift checks only report differences; they never modify
the repository or create issues. They label added/removed root or service keys as inventory drift;
a digest-only change with those sets unchanged is content-only drift requiring nested, prose, or
other non-inventory review. This bounded phase deliberately leaves all nested-schema drift outside
the inventory; nested coverage remains tracked below.

## Exact top-level gaps

There are no remaining closed-schema top-level gaps. `version` is retained with an obsolete-field
warning and never selects a provider or schema. `include` retains short paths and long
`path`/`env_file`/`project_directory` forms. Its completed traversal slice accepts
caller-authorized loading, uses effective no-interpolation declarations in depth-first order, and
retains origins, partial graphs, cycles, and global source-ID diagnostics. Its opt-in composition
slice recursively imports absent child services, networks, volumes, configs, secrets, and
individual models after each parent merge; local/earlier selections win exact-name collisions with
explicit source-aware warnings and no cross-project merge. Its opt-in project-directory plan
defaults root/undeclared children from retained first-document directories and delegates only
explicit declarations to caller policy with nested effective-parent context. It does not itself
canonicalize/join paths, read environment files or `.env`, infer names, cache diamonds, render a
composed document, or select provider behavior. `models` retains `name`, required `model`,
`context_size`, and `runtime_flags`. None of these operations performs implicit file, environment,
or provider access.
Malformed or unknown nested include/model members remain reachable through the effective view's
root or service `unmodeled_fields` references rather than being normalized away.

`name`, `services`, `networks`, `volumes`, `configs`, and `secrets` are document- and
project-typed.

## Exact service gaps

### Project-typed service keys

The effective project view currently exposes:

`annotations`, `blkio_config`, `cgroup`, `cgroup_parent`, `command`, `configs`, `container_name`, `cpu_count`, `cpu_percent`, `cpu_period`, `cpu_quota`, `cpu_rt_period`, `cpu_rt_runtime`, `cpu_shares`, `cpus`, `cpuset`, `device_cgroup_rules`, `ipc`, `mem_reservation`, `mem_swappiness`, `memswap_limit`, `network_mode`, `oom_kill_disable`, `oom_score_adj`, `pid`, `scale`, `volumes_from`, `credential_spec`, `depends_on`, `entrypoint`, `env_file`,
`environment`, `extends`, `extra_hosts`, `provider`, `build.additional_contexts`, `build.context`, `build.args`, `build.cache_from`, `build.cache_to`, `build.dockerfile`, `build.dockerfile_inline`, `build.entitlements`, `build.extra_hosts`, `build.target`, `build.network`, `build.isolation`, `build.platforms`, `build.no_cache`, `build.privileged`, `build.sbom`, `build.pull`, `build.shm_size`, `build.tags`, `build.labels`, `build.secrets`, `build.ssh`, `build.ulimits`, `cap_add`, `cap_drop`, `devices`, `dns`, `dns_opt`, `dns_search`,
`expose`, `group_add`, `healthcheck`, `hostname`, `image`, `init`, `platform`, `stdin_open`, `tty`, `privileged`, `attach`, `labels`, `logging`, `networks`, `ports`,
`post_start`, `pre_stop`, `pre_start`, `profiles`, `read_only`, `pids_limit`, `pull_policy`, `pull_refresh_after`, `restart`, `runtime`, `secrets`, `security_opt`,
`shm_size`, `mem_limit`, `stop_grace_period`, `stop_signal`, `sysctls`, `tmpfs`, `ulimits`, `user`,
`userns_mode`, `volumes`, and `working_dir`.

`deploy.endpoint_mode`, `deploy.labels`, `deploy.mode`, `deploy.placement`, `deploy.replicas`, and
`deploy.resources.limits.cpus`, `deploy.resources.limits.memory`, `deploy.resources.limits.pids`,
`deploy.resources.reservations.cpus`, `deploy.resources.reservations.devices[].capabilities`,
`deploy.resources.reservations.devices[].driver`,
`deploy.resources.reservations.devices[].count`,
`deploy.resources.reservations.devices[].device_ids`,
`deploy.resources.reservations.devices[].options`,
`deploy.resources.reservations.generic_resources`, `deploy.resources.reservations.memory`, `deploy.rollback_config`, and `deploy.update_config` are also native in
the effective project view: exact `vip`/`dnsrr` and `global`/`replicated` remain distinct from raw
portability-diagnosed `Other` strings, replicas preserves its exact YAML number spelling or distinct
string category, labels retain mapping scalar/null or ordered raw list forms separately from
service container labels, placement retains raw constraints, preferences, and maximum scalar
categories with complete merge provenance, resource-limit CPUs retain number/string categories,
memory retains string-only conservative classification, PIDs retain integer/string categories, and
reservation CPUs retain number/string categories while reservation memory reuses the string-only
classification. Reservation generic resources retain schema-only ordered list evidence: ordinary
append/reset/override provenance, mapping/unmodeled item form, and optional raw discrete kind/value
members. They make no prose, version, provider, matching, scheduling, device, runtime, or
conversion claim. Reservation-device capabilities, strict YAML-string drivers, raw integer/string
counts, and ordered strict-string IDs retain schema-only ordered evidence with duplicate and
conflict diagnostics, without selection/loading, allocation, grammar, scheduling, CDI, host,
runtime, or conversion claim. Options retain map/list syntax, scalar fidelity, malformed evidence,
duplicates, and generic provenance without provider interpretation. All current immediate deploy
children are native values; only malformed, extension, and future-unknown child evidence, plus the
explicitly bounded nested resource forms, remain unmodeled.
The prose `vip` default and schema lack of an effective default conflict, so no default,
integer/positive/zero rule, mode coupling, container-label, platform, discovery, VIP, DNS, replica,
scale, allocation, scheduling, placement, job, deployment, runtime, or conversion interpretation is
applied.

The effective project view also exposes `develop`, `domainname`, `external_links`, `gpus`,
`isolation`, `label_file`, `links`, `mac_address`, `models`, `storage_opt`, `use_api_socket`, and
`uts`. Model references are validated locally; GPU selectors, label files, links, sockets, and
watch actions remain inert data with no runtime, host, file, or provider access.
Malformed or future nested GPU and develop members are retained through the containing service's
`unmodeled_fields` references.

### Document-only service keys

All current service and immediate deploy keys have an effective-project path. Nested resource
coverage remains limited to the explicitly listed forms; malformed, extension, and future-unknown
deploy child evidence remains source-addressable.

The effective build view promotes raw list/scalar-map `additional_contexts`, scalar/long `context`, ordered raw `cache_from`/`cache_to`/`entitlements`, non-empty `dockerfile`, exact-string `dockerfile_inline`, Build-specific list/map `extra_hosts` with scalar or nested-list raw addresses, opaque `target`/`network`/`isolation`, ordered raw `platforms`/`tags`, map/list `args`/`labels`, boolean/string `no_cache`/`sbom`, boolean/expression `privileged`/`pull`, raw-preserving `shm_size`, service-equivalent ordered `ulimits`, short/long `secrets`, and sensitive list/scalar-map `ssh` with form, sensitivity, provenance, duplicates, empties, reset/override, and partial recovery.
Cache descriptors and platforms remain raw, `no_cache` and `sbom` strings remain uncoerced, and `pull` remains unresolved: none receives reference, path, credential, default, or build-execution inference. `sbom` does not parse generators or expose generated data.
`build.ssh` does not parse identifiers, paths, PEM, sockets, agents, mounts, or builder behavior; all grant values remain redacted by default. `build.entitlements` has no allowlist, privilege, BuildKit/platform, execution, or runtime claim; Docker Compose v2.27.0 is a badge with earlier/removal boundaries unknown. `build.dockerfile_inline` retains exact strings and conflict evidence with `dockerfile` but performs no Containerfile parsing, path/context access, secret scanning, build, Docker, BuildKit, or runtime inference; Docker Compose v2.17.0 is a badge with earlier/removal boundaries unknown. `build.shm_size` does not infer builder defaults, host state, allocation, or runtime behavior. All closed immediate Build keys are typed; malformed input, extensions, future unknown members, and deliberately bounded nested semantics remain source-addressable unmodeled evidence without I/O, builder execution, or runtime inference.
`build.privileged` retains literal booleans or deferred dollar expressions. Ordinary quoted
non-expression strings remain diagnosed source evidence rather than coerced booleans. Docker
Compose v2.15.0 is a badge with earlier/removal boundaries unknown; no privilege, platform,
runtime, or build behavior is inferred.
`build.provenance` retains only YAML boolean or opaque string form and no attestation parsing, generation, publication, validation, builder execution, or runtime claim; Docker Compose v2.39.0 is a badge with earlier/removal boundaries unknown.

### Syntax-preserved-only service keys

There are no remaining closed-schema service-key gaps. `develop.watch` retains its documented
members and local shape diagnostics without watching paths or executing actions. `gpus` retains
the exact `all` scalar or list selectors without allocating devices. `label_file`,
`external_links`, and `links` preserve authored order without reading or resolving their targets.

## Nested resource coverage

All currently audited top-level resource-definition members are typed. Configs retain labels and
opaque strict-string template drivers. Secrets retain opaque strict-string drivers/template drivers,
ordered string-or-number driver options, and labels. Networks, volumes, configs, and secrets retain
the current boolean/expression `external` form separately from deprecated `external: { name: ... }`.
Legacy objects receive a migration warning and a two-span conflict diagnostic when they coexist with
current `name`; they are not normalized. The Compose schema deprecates this object for networks,
volumes, and configs, while Docker Compose 5.4.0 warned for all four: ComposeLens documents that
divergence rather than claiming universal provider behavior.

The existing service `ports`, `volumes`, `networks`, `configs`, and `secrets` types retain their
documented short/long forms. Future schema additions must first enter this ledger before support is
claimed.

## Exact nested semantic coverage

The 93-key service ledger above classifies immediate service keys. The following closed nested
keys have dedicated typed forms with intentionally bounded semantics. Open-ended user maps such
as labels, environment variables, driver options, and extension fields are intentionally not
enumerated. Service logging's `driver` and ordered scalar `options` are typed.

`develop.watch[].exec` retains null/scalar/list `command`, strict-string `user` and `working_dir`,
literal/deferred `privileged`, and list/map `environment` without watching, executing, resolving a
user/path, or reading environment files. `sync+exec` still requires a non-empty command.

`deploy.endpoint_mode`, `deploy.labels`, `deploy.mode`, `deploy.placement`, `deploy.replicas`,
`deploy.resources.limits.cpus`, `deploy.resources.limits.memory`, `deploy.resources.limits.pids`,
`deploy.resources.reservations.cpus`, `deploy.resources.reservations.devices[].capabilities`,
`deploy.resources.reservations.devices[].driver`,
`deploy.resources.reservations.devices[].count`,
`deploy.resources.reservations.devices[].device_ids`,
`deploy.resources.reservations.devices[].options`,
`deploy.resources.reservations.generic_resources`,
`deploy.resources.reservations.memory`, `deploy.restart_policy`, `deploy.rollback_config`, and `deploy.update_config` complete the current immediate deploy children. Nested resource coverage remains
limited to the explicitly listed forms, while malformed, extension, and future-unknown deploy
children remain source field references. Placement retains ordered raw
constraints/preferences and YAML integer/string maximum categories with merge provenance, but no
constraint grammar, node selection, count/default, scheduling, runtime, or conversion
interpretation. Restart-policy members retain raw spelling and member provenance without
service-restart fallback/default/precedence, simulation, runtime, or conversion interpretation.
map/list `build.additional_contexts`, `build.context`, map/list `build.args`, `build.labels`, and Build-specific `build.extra_hosts`, ordered raw `build.cache_from`/`build.cache_to`/`build.entitlements`, non-empty `build.dockerfile`, exact-string `build.dockerfile_inline`, opaque
`build.target`/`build.network`/`build.isolation`, ordered raw `build.platforms`/`build.tags`, boolean/string `build.no_cache`/`build.sbom`/`build.provenance`, scalar/list `build.no_cache_filter`, boolean/expression `build.privileged`/`build.pull`, raw-preserving `build.shm_size`, service-equivalent `build.ulimits`, and short/long `build.secrets`
are the promoted build values; their complete closed-key boundary remains open:

- `build`: all current immediate subkeys are promoted;
- `deploy`: all current immediate subkeys are promoted; nested resource coverage remains bounded;
- `deploy.resources.limits`: complete;
- `deploy.resources.reservations`: complete;
- `deploy.resources.reservations.devices[]`: complete;

Conversely, the current nested keys under `depends_on`, `env_file`, `healthcheck`, service
`networks`, service `ports`, service config/secret grants, network `ipam`, and service `ulimits`
already have dedicated document types. This distinction prevents an immediate parent key from
hiding a nested semantic gap.

## Generated-document boundary

Generated documents currently cover project `name`, services, networks, volumes, file-backed
configs, and file-backed secrets. Generated
services cover `hostname`, `container_name`, `image`, `entrypoint`, `command`, `init`, `stdin_open`, `tty`, `privileged`, `env_file`, `environment`, `labels`, `annotations`, `logging`, `user`,
`userns_mode`, `group_add`, `cap_add`, `cap_drop`, `working_dir`, `read_only`, `pids_limit`, `shm_size`, `tmpfs`, `sysctls`, `ulimits`, `pull_policy`, `restart`, `stop_signal`,
`stop_grace_period`, `extra_hosts`, `ports`, `cpu_rt_runtime`, `cpu_shares`, `cpus`, `cpuset`,
`device_cgroup_rules`, `ipc`, `mem_reservation`, `mem_swappiness`, `memswap_limit`,
`network_mode`, `oom_kill_disable`, `oom_score_adj`, `pid`, `scale`, `volumes_from`,
`volumes`, `networks`, raw resolved `domainname`/`isolation`/`mac_address`/`uts`, literal
`use_api_socket`, and scalar `gpus: all`. Generated GPU lists, driver metadata, resource metadata,
and develop watches remain intentionally outside this boundary.
Generated long-form service-network attachments retain aliases plus optional raw `ipv4_address`
and `ipv6_address` values with omission, sensitivity, and named-network scope intact.
Generated top-level network definitions add optional opaque `driver` and ordered unique
string-or-number `driver_opts` without changing the shared basic/external `GeneratedResource`
network API. They are application-owned; external definitions remain `GeneratedResource::external`
because Compose permits only `name` alongside `external`. Driver/plugin and provider-specific option
semantics remain outside generation.

Generated top-level volume definitions use a separate application-owned API with optional opaque
`driver` and ordered unique string-or-number `driver_opts`. It preserves explicit empty maps and
scalar shape without accepting driver-configured external volumes; `GeneratedResource::external`
remains the compatible external lifecycle API. BoxFerry owns conversion outcomes for general
volume driver options, image drivers, external lifecycle, and platform names.
Application-owned generated volume definitions also retain ordered unique explicit-string `labels`,
including omission, explicit empty maps, deterministic parse-back output, and sensitivity. Literal
external volumes that retain labels have distinct source-aware diagnostics; external lifecycle
remains unavailable on the application-owned definition API.

Generated application-owned network definitions also retain optional literal `enable_ipv6` and
`internal` choices, including omission versus explicit `false` or `true`, without defaults or
driver/IPAM/provider/runtime validation. `enable_ipv4` remains deliberately absent from this
generated API because it has no native Quadlet/Podman network-create counterpart; BoxFerry owns
the non-representable diagnostic.

Generated config and secret definitions accept one unique resolved single-line name plus one
required resolved single-line `file` value. Their deterministic minimally quoted mappings parse back through
the native model and propagate caller-marked file sensitivity. Content, environment, external
lifecycle, drivers, labels, template drivers, and file access remain deliberately outside this
minimal generated subset.

### Recurring generation-admission rule

Generated construction is demand-driven, not a remaining-key count. A maintainer may admit a
field only after its syntax-form choice, invalid-value rejection, sensitivity behavior,
deterministic rendering, and parse-back tests are defined. All other typed or preserved fields stay
intentionally ungenerated until a concrete consumer need justifies that review.

## Implementation order

### Phase 1: high-value process and lifecycle parity

- [x] Type `entrypoint` at document and project layers without conflating it with `command`, and
      add deterministic generated string, list, and empty forms.
- [x] Type `init` as a source-aware/interpolation-preserving boolean and add deterministic
      generated output.
- [x] Type independent `stop_grace_period` and `stop_signal` fields through generated output.
- [x] Type and generate raw-preserving `pull_policy` values while keeping schema-only `refresh`
      distinct and provider evidence planned.
- [x] Type `stdin_open` as an independent source-aware/interpolation-preserving boolean and add
      deterministic generated output.
- [x] Type `tty` as an independent source-aware/interpolation-preserving boolean and add
      deterministic generated output.
- [x] Type `privileged` as an independent source-aware/interpolation-preserving boolean and add
      deterministic generated output without inferring security or runtime behavior.
- [x] Type `attach` as an independent source-aware/interpolation-preserving boolean through the
      authored and effective views, without a default, generated API, logging, runtime, provider, CLI,
      compatibility, or cross-format behavior.
- [x] Type `pull_refresh_after` as a strict raw YAML string with deferred-value retention and no
      refresh, provider, or compatibility inference.
- [x] Type `runtime` as a strict raw YAML string with deferred-value retention and no provider or
      compatibility inference.
- [x] Type `platform` as a strict raw YAML string with deferred-value retention and no OCI, host,
      image, build, provider, or compatibility inference.
- Generation admission is a recurring maintainer rule: add a field only after its complete
  null/empty/short/long contract, validation, sensitivity, deterministic rendering, and
  parse-back tests are reviewed.

### Phase 2: limits, security, devices, and storage

- [x] Type service `pids_limit` through the authored, effective-project, and generated boundaries
      without normalizing zero or conflating it with `deploy.resources.limits.pids`.
- [x] Type service `shm_size` through the authored, effective-project, and generated boundaries
      with exact YAML scalar provenance, documented lowercase units, ambiguous zero, provider-dependent
      states, and no injected default or runtime inspection.
- [x] Type service `cap_drop` through authored, exact-scalar merge, effective-project, and generated
      boundaries while preserving explicit empty state, case, provenance, and planned-only provider
      evidence without target logic or a capability whitelist.
- [x] Type service `cap_add` through authored, exact-scalar merge, effective-project, and generated
      boundaries while preserving explicit empty state, case, provenance, independent coexistence
      with `cap_drop`, and planned-only provider evidence without target logic or a capability
      whitelist.
- [x] Promote `ulimits` through recursive mapping merge, the effective project view, and safe
      generated output while retaining ordered names, single/range form, nested provenance,
      sensitivity, empty/reset/override state, and planned-only provider evidence.
- [x] Promote the complete closed immediate Build-key family—`additional_contexts`, context, args, labels, Build-specific `extra_hosts`, raw `cache_from`/`cache_to`/`entitlements`, Dockerfile/inline Dockerfile/target/network/isolation/platforms/no_cache/privileged/sbom/pull/shm_size/tags, `ulimits`, and short/long `build.secrets`—with source form, sensitivity, provenance, recovery, and retained conflict evidence. Only malformed input, extensions, future unknown members, and deliberately bounded nested semantics remain unmodeled.
- [x] Promote `deploy.endpoint_mode`, map/list `deploy.labels`, `deploy.mode`, and raw-preserving `deploy.replicas`
      into the effective project view with provenance and nested unmodeled siblings; no container-label, integer/default,
      mode-coupling, scheduling, runtime, or conversion semantics are inferred before deepening further deploy types.
- [x] Promote deploy-specific `restart_policy` members through authored and effective views with
      raw condition/duration/attempt spelling, member provenance, and nested malformed/reset evidence;
      no service-restart fallback/default/precedence, simulation, runtime, or conversion behavior is
      inferred.
- [x] Promote deploy `placement` constraints, preferences, and max-replicas-per-node scalar
      categories through authored and effective views with nested provenance and recovery, without
      scheduling, node-selection, default, runtime, or conversion semantics.
- [x] Promote deploy `resources.limits.pids` through authored and effective views with exact
      integer/string spelling, nested provenance, recovery, and no service-PID, host, cgroup, runtime,
      or conversion semantics.
- [x] Promote deploy `resources.limits.cpus` through authored and effective views with exact
      number/string spelling, nested provenance, recovery, and no service CPU, `mem_limit`, host,
      cgroup, runtime, or conversion semantics.
- [x] Promote deploy `resources.limits.memory` through authored and effective views with raw
      YAML-string spelling, conservative lowercase-unit classification, nested provenance, recovery,
      and no service `mem_limit`, reservation, host, cgroup, runtime, or conversion semantics.
- [x] Promote deploy `resources.reservations.cpus` through authored and effective views with exact
      number/string spelling, nested provenance, recovery, and no limit/service CPU, scheduling, host,
      cgroup, runtime, target, or conversion semantics.
- [x] Promote deploy `resources.reservations.memory` through authored and effective views with raw
      YAML-string spelling, conservative lowercase-unit classification, nested provenance, recovery,
      and no limit/service `mem_limit`, scheduling, host, cgroup, runtime, target, or conversion semantics.
- [x] Promote schema-backed deploy `resources.reservations.generic_resources` lists with optional
      discrete-specification kind/value members, raw scalar spelling, provenance, recovery, and no
      matching, scheduling, GPU/device, runtime, target, or conversion semantics.
- [x] Promote schema-only deploy `resources.reservations.devices[]` capability lists, strict
      YAML-string `.driver`, raw integer-or-string `.count`, and ordered strict-string `.device_ids`
      with duplicate/conflict diagnostics, nested provenance, recovery, and no selection/loading,
      allocation, grammar, scheduling, CDI, host, runtime, cgroup, provider/version, or conversion
      semantics. Options retain map/list syntax, scalar fidelity, malformed evidence, duplicates, and
      generic provenance without provider interpretation.
- [x] Type all CPU, memory, PID, OOM, and block-I/O keys without applying host defaults.
- [x] Type service `devices` through authored, Compose-Go-compatible target merge,
      effective-project, and generated boundaries while preserving mixed raw short/long forms,
      CDI/deferred/opaque evidence, duplicates, nested provenance, reset/override, and planned-only
      provider evidence without device, permissions, CDI, GPU, or runtime validation.
- [x] Type immediate service `gpus`, `storage_opt`, and UTS namespace choices through authored
      and effective-project views without device allocation, label-file I/O, or runtime inference.
- Deploy reservation devices are complete as bounded structured source data: capabilities, driver,
  count, IDs, and options remain source evidence rather than allocation requests. Allocation,
  selection, and provider/runtime behavior stay consumer-led unless a separately reviewed ADR
  establishes a narrower native contract.
- [x] Type service-level `tmpfs` through authored, ordinary-append merge, effective-project, and
      generated boundaries while preserving scalar/list form, duplicates, colon-delimited raw options,
      provenance, sensitivity, reset/override, and planned-only provider evidence.
- [x] Type service `sysctls` through authored, generic map/list merge, effective-project, and
      generated boundaries while preserving form, scalar spelling, duplicate evidence, provenance,
      sensitivity, reset/override, and planned-only provider evidence without runtime interpretation.
- [x] Type `volumes_from` through authored, effective-project, reference-validation, and generated
      boundaries while preserving order, duplicates, reset/override provenance, and raw access modes.
- [x] Type the remaining long service-volume members through authored and effective views:
      `consistency`, `bind.recursive`, and the `image`, `tmpfs`, and `volume` blocks including
      `image.subpath`, `tmpfs.size`, `tmpfs.mode`, `volume.labels`, `volume.nocopy`, and
      `volume.subpath`. Generation remains intentionally out of scope. `tmpfs.mode` carries a
      Compose v2.14 badge and `image.subpath` a Compose v2.35 badge; all other availability
      boundaries remain unknown. No path, image, volume, permission, provider, runtime, default,
      or filesystem behavior is inferred.

### Phase 3: networking, identity, and metadata

- [x] Type and generate service `hostname` with conservative RFC-1123 validation, deferred and
      invalid authored states, complete merge provenance, and planned-only provider evidence.
- [x] Type and generate service DNS settings with their documented merge rules and raw evidence.
- [x] Type and generate exposed ports with scalar-kind-aware uniqueness.
- [x] Generate optional raw per-attachment IPv4/IPv6 addresses in deterministic long-form service
      networks without inferring IPAM defaults or validating address/pool relationships.
- [x] Generate top-level network drivers and scalar-kind-aware ordered driver options without
      changing the shared basic/external resource API, while keeping external networks on its
      name-only-compatible path and not validating plugins or provider semantics.
- [x] Preserve and generate raw service security options with non-selecting diagnostic candidates.
- [x] Type network modes through authored, effective-project, reference-validation, and generated
      boundaries without inferring runtime namespaces or provider behavior.
- [x] Type domain name, MAC addresses, external links, and links through authored and effective
      project views without network or runtime resolution.
- [x] Type service annotations through authored mapping/list syntax, keyed effective merge,
      provenance-preserving diagnostics, and safe generated mapping output.
- [x] Type service `logging` through authored, recursively merged, effective-project, and generated
      boundaries with uninterpreted drivers, ordered string/number/null options, and no provider policy.
- [x] Type `label_file` scalar/list syntax with source and merge provenance; label files remain
      unread. Config/secret metadata stays in the nested-resource ledger.
- Provider spellings are complete as raw preservation with a bounded current evidence audit; this
  is not a blanket compatibility claim. Future provider/version observations are added only
  when they affect a supported contract or explain a concrete regression.

### Phase 4: orchestration and processing-only features

- [x] Implement the bounded top-level `include` traversal: caller-authorized recursive loading,
      effective no-interpolation ordering, origins, partial graph diagnostics, cycles, and global
      source-ID rejection.
- [x] Compose included resources without I/O: recursive local-wins imports for all six top-level
      namespaces, explicit conflicts, and retained occurrence/source evidence.
- [x] Plan include project directories without I/O: first-document defaults, explicit caller-owned
      resolver outcomes, nested parent propagation, and redacted source-aware unresolved errors.
- [x] Resolve selected included service bind sources plus config and secret `file` paths lexically
      from authorized occurrence bases, with explicit unavailable/mismatched-plan diagnostics and
      no root fallback.
- Other path families—including build, `env_file`, `label_file`, `extends.file`, develop-watch,
  include loading, URI/non-local policy, and composed rendering—are explicitly deferred to a
  field-specific consumer need and ADR. Environment-file/`.env` precedence, project-name rules,
  and provider-specific behavior remain separate application or evidence decisions.
- [x] Type `develop`, service/top-level `models`, and `use_api_socket` without implying that every
      provider executes them.
- Parser I/O purity is a permanent invariant: file reads, environment access, and provider/runtime
  invocation remain outside parsing APIs and are protected by focused regression and policy
  tests.

### Phase 5: generation, compatibility, and conformance

- Generated expansion is recurring and demand-driven: admit only consumer-needed fields under the
  generation-admission rule above.
- The current Docker Compose and Podman Compose evidence audit is complete for supported claims;
  it makes no blanket provider/version compatibility claim. New evidence is collected only for
  a supported behavior change, contradiction, or regression.
- Real-world corpus intake is recurring and regression-driven: add a minimal licensed immutable
  fixture only when it captures a concrete missing behavior or prevents a regression.
- [x] Maintain the commit-pinned root/service schema snapshot and a classified inventory with
      offline digest, closed-shape, extension-allowance, and exact-key-set policy tests. Scheduled
      upstream drift reporting is manual/scheduled only. Nested-schema drift is a recurring intake
      boundary and expands only when a concrete changed field enters the supported contract.

## Completion rule

A key is complete only when the repository documents its syntax forms, exposes source-aware native
types, implements effective merge/profile behavior where applicable, tests malformed recovery and
provenance, and separately records generation and provider compatibility status. Syntax
preservation alone is valuable, but never counts as semantic completion.