pg-maker 0.1.0__py3-none-any.whl

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 (181) hide show
  1. pg_maker/__init__.py +3 -0
  2. pg_maker/__main__.py +3 -0
  3. pg_maker/api.py +594 -0
  4. pg_maker/artifacts/__init__.py +4 -0
  5. pg_maker/artifacts/catalog.py +67 -0
  6. pg_maker/artifacts/manifest.py +301 -0
  7. pg_maker/assets.py +93 -0
  8. pg_maker/builders/__init__.py +4 -0
  9. pg_maker/builders/autotools.py +430 -0
  10. pg_maker/builders/components.py +359 -0
  11. pg_maker/bundled/PROJECT.md +57 -0
  12. pg_maker/bundled/build.yaml +29 -0
  13. pg_maker/bundled/components/pg-stat-kcache.yaml +30 -0
  14. pg_maker/bundled/components/pg-stat-statements.yaml +24 -0
  15. pg_maker/bundled/components/pg-wait-sampling.yaml +30 -0
  16. pg_maker/bundled/config/defaults.yaml +80 -0
  17. pg_maker/bundled/config/documentation.yaml +24 -0
  18. pg_maker/bundled/config/features/my-feature.yaml +17 -0
  19. pg_maker/bundled/config/vendor.yaml +13 -0
  20. pg_maker/bundled/documentation/README.md +20 -0
  21. pg_maker/bundled/documentation/pg-stat-kcache.sgml +99 -0
  22. pg_maker/bundled/documentation/pg-stat-kcache.yaml +15 -0
  23. pg_maker/bundled/documentation/pg-wait-sampling.sgml +122 -0
  24. pg_maker/bundled/documentation/pg-wait-sampling.yaml +15 -0
  25. pg_maker/bundled/patches/unix-socket-directory.patch +5 -0
  26. pg_maker/changes/__init__.py +1 -0
  27. pg_maker/changes/apply.py +298 -0
  28. pg_maker/changes/loader.py +135 -0
  29. pg_maker/changes/workspace.py +221 -0
  30. pg_maker/cli.py +546 -0
  31. pg_maker/components/__init__.py +4 -0
  32. pg_maker/config.py +514 -0
  33. pg_maker/development/__init__.py +1 -0
  34. pg_maker/development/cli.py +104 -0
  35. pg_maker/development/git.py +362 -0
  36. pg_maker/development/session.py +735 -0
  37. pg_maker/documentation/__init__.py +4 -0
  38. pg_maker/documentation/builder.py +467 -0
  39. pg_maker/documentation/cli.py +24 -0
  40. pg_maker/documentation/config.py +127 -0
  41. pg_maker/documentation/install.py +79 -0
  42. pg_maker/documentation/site.py +166 -0
  43. pg_maker/documentation/sphinx_ext.py +150 -0
  44. pg_maker/documentation/theme/_static/pg-maker.css +26 -0
  45. pg_maker/documentation/theme/_static/pg-maker.js +35 -0
  46. pg_maker/documentation/theme/_templates/footer_en.html +5 -0
  47. pg_maker/documentation/theme/_templates/footer_metadata.html +13 -0
  48. pg_maker/documentation/theme/_templates/footer_ru.html +5 -0
  49. pg_maker/documentation/translation.py +341 -0
  50. pg_maker/documentation/validation.py +132 -0
  51. pg_maker/documentation/worker.py +62 -0
  52. pg_maker/documentation/writer.py +324 -0
  53. pg_maker/documentation/xml.py +210 -0
  54. pg_maker/documents.py +118 -0
  55. pg_maker/errors.py +50 -0
  56. pg_maker/execution/__init__.py +1 -0
  57. pg_maker/execution/build.py +502 -0
  58. pg_maker/execution/cache.py +287 -0
  59. pg_maker/execution/cancellation.py +60 -0
  60. pg_maker/execution/checkpoints.py +218 -0
  61. pg_maker/execution/cleanup.py +122 -0
  62. pg_maker/execution/component_cache.py +164 -0
  63. pg_maker/execution/development.py +109 -0
  64. pg_maker/execution/engine.py +171 -0
  65. pg_maker/execution/events.py +65 -0
  66. pg_maker/execution/incremental.py +178 -0
  67. pg_maker/execution/preparation.py +130 -0
  68. pg_maker/execution/process.py +155 -0
  69. pg_maker/execution/resources.py +41 -0
  70. pg_maker/execution/state.py +82 -0
  71. pg_maker/execution/worker.py +45 -0
  72. pg_maker/identity.py +116 -0
  73. pg_maker/integrations/__init__.py +1 -0
  74. pg_maker/integrations/machine.py +163 -0
  75. pg_maker/integrations/runtime.py +387 -0
  76. pg_maker/models.py +245 -0
  77. pg_maker/packaging/__init__.py +4 -0
  78. pg_maker/packaging/deb.py +337 -0
  79. pg_maker/packaging/service.py +165 -0
  80. pg_maker/packaging/spec.py +64 -0
  81. pg_maker/packaging/templates/deb-control.in +8 -0
  82. pg_maker/packaging/tree.py +239 -0
  83. pg_maker/planning/__init__.py +1 -0
  84. pg_maker/planning/documents.py +65 -0
  85. pg_maker/planning/environments.py +318 -0
  86. pg_maker/planning/graph.py +23 -0
  87. pg_maker/planning/plan.py +418 -0
  88. pg_maker/planning/resolve.py +117 -0
  89. pg_maker/planning/reuse.py +80 -0
  90. pg_maker/planning/runtime_repository.py +90 -0
  91. pg_maker/postgresql.py +59 -0
  92. pg_maker/progress.py +64 -0
  93. pg_maker/publishing/__init__.py +4 -0
  94. pg_maker/py.typed +0 -0
  95. pg_maker/recipes/README.md +13 -0
  96. pg_maker/recipes/platforms/debian-13.yaml +125 -0
  97. pg_maker/recipes/postgresql.yaml +114 -0
  98. pg_maker/runners/__init__.py +1 -0
  99. pg_maker/runners/base.py +29 -0
  100. pg_maker/runners/docker.py +312 -0
  101. pg_maker/schemas/build.schema.json +5 -0
  102. pg_maker/schemas/change-set.schema.json +5 -0
  103. pg_maker/schemas/component-envelope.schema.json +69 -0
  104. pg_maker/schemas/component.schema.json +5 -0
  105. pg_maker/schemas/defaults.schema.json +5 -0
  106. pg_maker/schemas/doc-rules.schema.json +5 -0
  107. pg_maker/schemas/documentation.schema.json +5 -0
  108. pg_maker/schemas/environment.schema.json +228 -0
  109. pg_maker/schemas/feature.schema.json +5 -0
  110. pg_maker/schemas/insertions.schema.json +5 -0
  111. pg_maker/schemas/lock.schema.json +3963 -0
  112. pg_maker/schemas/operation-input.schema.json +306 -0
  113. pg_maker/schemas/operation-state.schema.json +127 -0
  114. pg_maker/schemas/plan.schema.json +284 -0
  115. pg_maker/schemas/planning-common.schema.json +8192 -0
  116. pg_maker/schemas/platform.schema.json +5 -0
  117. pg_maker/schemas/postgresql-catalog.schema.json +5 -0
  118. pg_maker/schemas/run-event.schema.json +72 -0
  119. pg_maker/schemas/translations.schema.json +5 -0
  120. pg_maker/schemas/vendor.schema.json +5 -0
  121. pg_maker/security.py +73 -0
  122. pg_maker/sources/__init__.py +1 -0
  123. pg_maker/sources/resolver.py +238 -0
  124. pg_maker/sources/store.py +279 -0
  125. pg_maker/storage.py +127 -0
  126. pg_maker/validation/__init__.py +4 -0
  127. pg_maker/validation/installed.py +667 -0
  128. pg_maker/validation/packages.py +309 -0
  129. pg_maker/validation/systemctl.py +185 -0
  130. pg_maker/yamlio.py +54 -0
  131. pg_maker-0.1.0.data/data/share/doc/pg-maker/CHANGELOG.md +22 -0
  132. pg_maker-0.1.0.data/data/share/doc/pg-maker/CONTRIBUTING.md +63 -0
  133. pg_maker-0.1.0.data/data/share/doc/pg-maker/LICENSE +21 -0
  134. pg_maker-0.1.0.data/data/share/doc/pg-maker/README.md +163 -0
  135. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/architecture.md +55 -0
  136. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/development-storage.md +72 -0
  137. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/development.md +86 -0
  138. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/README.md +32 -0
  139. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/api.md +75 -0
  140. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/build.md +112 -0
  141. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/changes.md +58 -0
  142. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/cleanup.md +17 -0
  143. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/components.md +39 -0
  144. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/configuration.md +83 -0
  145. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/development.md +88 -0
  146. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/documentation.md +241 -0
  147. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/documents.md +42 -0
  148. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/environments.md +40 -0
  149. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/execution.md +49 -0
  150. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/machine.md +31 -0
  151. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/observability.md +28 -0
  152. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/packaging.md +107 -0
  153. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/planning.md +63 -0
  154. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/postgresql.md +79 -0
  155. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/publication.md +20 -0
  156. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/recovery.md +83 -0
  157. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/runtime.md +31 -0
  158. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/sources.md +48 -0
  159. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/state.md +49 -0
  160. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/interfaces/storage.md +24 -0
  161. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/releasing.md +98 -0
  162. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/reuse.md +24 -0
  163. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/roadmap.md +54 -0
  164. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/default-components.md +56 -0
  165. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/development-release.md +49 -0
  166. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/documentation-theme.md +45 -0
  167. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/integration.md +49 -0
  168. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/postgresql-majors.md +107 -0
  169. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/review-fixes.md +68 -0
  170. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/stage4.md +65 -0
  171. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/stage56.md +66 -0
  172. pg_maker-0.1.0.data/data/share/doc/pg-maker/docs/validation/stage7.md +72 -0
  173. pg_maker-0.1.0.data/data/share/doc/pg-maker/tests/fixtures/guc/README.md +11 -0
  174. pg_maker-0.1.0.data/data/share/doc/pg-maker/tests/fixtures/stage4/README.md +31 -0
  175. pg_maker-0.1.0.data/data/share/doc/pg-maker/tests/fixtures/stage7/README.md +16 -0
  176. pg_maker-0.1.0.dist-info/METADATA +200 -0
  177. pg_maker-0.1.0.dist-info/RECORD +181 -0
  178. pg_maker-0.1.0.dist-info/WHEEL +5 -0
  179. pg_maker-0.1.0.dist-info/entry_points.txt +4 -0
  180. pg_maker-0.1.0.dist-info/licenses/LICENSE +21 -0
  181. pg_maker-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,163 @@
1
+ # pg_maker
2
+
3
+ A Python controller for building PostgreSQL distributions, packages and documentation
4
+ in isolated Docker environments. It also provides Git development sessions for
5
+ editing patches, recovering failed builds and rebuilding individual extensions.
6
+
7
+ The current package is an **alpha**. The implemented platform is Debian 13 / x86_64,
8
+ with release/debug builds and DEB packages. The PostgreSQL catalog covers majors
9
+ 14–19, including beta/RC identities; versions below 14 are unsupported. Catalog
10
+ coverage is distinct from validation coverage: see the [major-version report](docs/validation/postgresql-majors.md).
11
+ RPM, other platforms and distribution repository publishing remain on the
12
+ [roadmap](docs/roadmap.md).
13
+
14
+ ## Installation
15
+
16
+ Requires Linux and Python 3.10+. Container operations require a local Docker daemon;
17
+ Git development sessions also require Git. Installing the Python package and reading
18
+ capabilities do not require Docker.
19
+
20
+ From PyPI:
21
+
22
+ ```bash
23
+ python3 -m venv .venv
24
+ .venv/bin/python -m pip install pg-maker
25
+ .venv/bin/pg-maker --help
26
+ ```
27
+
28
+ For development, from a source checkout:
29
+
30
+ ```bash
31
+ python3 -m venv .venv
32
+ .venv/bin/python -m pip install -e '.[dev]'
33
+ .venv/bin/pg-maker --help
34
+ .venv/bin/pg-maker --component-capabilities
35
+ .venv/bin/pg-maker doctor --machine
36
+ ```
37
+
38
+ A built wheel can be installed with `python -m pip install /path/to/pg_maker-VERSION-py3-none-any.whl`.
39
+
40
+ ## Build a distribution
41
+
42
+ ```bash
43
+ pg-maker init example
44
+ pg-maker validate example/build.yaml
45
+ pg-maker config show example/build.yaml --resolved
46
+ pg-maker env prepare example/build.yaml --out example/environments.json --operations example/operations
47
+ pg-maker resolve example/build.yaml --environments example/environments.json --out example/lock.json --input-store example/inputs --operations example/operations
48
+ pg-maker plan example/lock.json --out example/plan.json --goal build
49
+ pg-maker build example/lock.json --plan example/plan.json --operations example/operations --detach
50
+ ```
51
+
52
+ `init` creates editable vendor/defaults/documentation YAML, a `my-feature` variant,
53
+ component recipes, schemas and the built-in socket-directory patch. The initial
54
+ target is PostgreSQL 18.1 / Debian 13 / x86_64 / DEB, without documentation.
55
+ The default components are `pg_stat_statements`, `pg_stat_kcache 2.3.2` and
56
+ `pg_wait_sampling 1.1.11`. External sources are pinned by commit SHA. Set
57
+ `components: []` to omit additional extensions. See [component recipes](docs/interfaces/components.md).
58
+
59
+ `env prepare` downloads missing base images and installs dependencies inside
60
+ containers. Its result records build/test image IDs, package versions and toolchain
61
+ inventory. `resolve` freezes source commits, submodules, snapshots, archive
62
+ checksums and ChangeSets in a BuildLock. Offline resolution reuses stored inputs
63
+ and reports missing ones. Both operations support `--detach` and `--request-id`.
64
+
65
+ The build user defaults to `1000:1000` and must match the non-root owner of the
66
+ workspace. Environment preparation creates this user inside the image. Build
67
+ commands run with networking disabled. Outputs stay inside the operation directory.
68
+
69
+ **Database tests are disabled by default while developing the utility.** A normal
70
+ build compiles the candidate and components without `check`, `check-world`,
71
+ component tests, acceptance tests or a baseline build. Reports remain `unverified`,
72
+ with `db_tests=skipped` and `publication_eligible=false`. Tests of pg_maker itself
73
+ remain enabled.
74
+
75
+ Use `--goal package` to build server/client/libpq DEBs, manifests, installation
76
+ instructions and HTML/JSON reports. A quick package build remains unverified.
77
+ The long source/database test adapter currently supports major 18 only:
78
+
79
+ ```bash
80
+ pg-maker build example/lock.json --run-db-tests --operations example/operations
81
+ # Explicitly requests source and installed-package qualification:
82
+ pg-maker build example/lock.json --goal verified --operations example/operations
83
+ ```
84
+
85
+ A supplied plan controls the test mode; create it with `plan --run-db-tests` when
86
+ needed. `--skip-db-tests` explicitly selects the quick path. Successful source
87
+ suites grant at most `source-verified`; `package-verified` requires installed-package
88
+ qualification too. See [build](docs/interfaces/build.md) and [packaging](docs/interfaces/packaging.md).
89
+
90
+ ## Build documentation only
91
+
92
+ ```bash
93
+ pg-maker init docs-project --with-doc --doc-language en
94
+ pg-maker env prepare docs-project/build.yaml --out docs-project/environments.json
95
+ pg-maker resolve docs-project/build.yaml --environments docs-project/environments.json --out docs-project/lock.json
96
+ pg-maker docs build docs-project/lock.json
97
+ ```
98
+
99
+ `docs build` builds documentation without compiling the server or producing DEBs.
100
+ It accepts official archive/Git sources or a snapshot of a locally modified source
101
+ tree. Set `branding: none` for upstream PostgreSQL branding. The default HTML uses
102
+ `sphinx_book_theme`, with an expandable sidebar, page contents and local search.
103
+ The footer uses the selected product, version, feature, language and optional vendor
104
+ links. `html_backend: docbook` selects the original DocBook layout explicitly.
105
+
106
+ `config/documentation.yaml` selects HTML/man/PDF. The two external extensions'
107
+ guides join the main Sphinx HTML/PDF manual when documentation is enabled.
108
+ Russian PostgreSQL output requires a complete, current external translation bundle;
109
+ the project's own Markdown documentation is English. HTML/PDF can be packaged in
110
+ a separate docs DEB, with manpages assigned to the packages that own their commands.
111
+ See the [documentation contract](docs/interfaces/documentation.md).
112
+
113
+ ## Develop code and patches
114
+
115
+ ```bash
116
+ pg-maker dev open development --from-run example/operations/FAILED_RUN
117
+ pg-maker dev status development
118
+ # Edit the source paths returned by status, then record a patch:
119
+ pg-maker dev patch development commit --scope component:pg-wait-sampling --id fix-build
120
+ pg-maker dev explain development --component pg-wait-sampling
121
+ pg-maker dev build development --component pg-wait-sampling
122
+ ```
123
+
124
+ Each session owns real Git repositories. It can import an existing local repository
125
+ with history, maintain intermediate commits, refresh patches, pop/push a series and
126
+ resolve rebase conflicts. New iterations freeze changed inputs into new locks;
127
+ `resume` retains its original meaning: retry the same operation with the same inputs.
128
+ Independent extensions and the core can be reused when their inputs match. Header,
129
+ ABI, toolchain and declared dependency changes invalidate affected results.
130
+ [Development guide](docs/development.md) and [interface contract](docs/interfaces/development.md).
131
+
132
+ ## Observe and retain results
133
+
134
+ ```bash
135
+ pg-maker status example/operations/RUN --machine
136
+ pg-maker events example/operations/RUN --after-sequence 0 --limit 20 --machine
137
+ pg-maker wait example/operations/RUN --timeout 120 --machine
138
+ pg-maker cancel example/operations/RUN --machine
139
+ pg-maker export example/operations/RUN --out exported-result
140
+ ```
141
+
142
+ The detached worker owns the operation. Closing a waiting CLI does not cancel it;
143
+ cancellation is explicit and repeatable. `status` returns success when it can read
144
+ the operation, even if the operation failed; `wait` returns the operation's exit code.
145
+ The [Python API](docs/interfaces/api.md) and optional pg_play CLI/MCP integration
146
+ use the same service and machine contract.
147
+
148
+ Source stores, workspaces, checkpoints and Docker caches consume disk space.
149
+ Check `df -h`, workspace sizes and `docker system df` before long runs. Use explicit
150
+ preview/apply cleanup and preserve needed outputs. See [storage and cleanup](docs/development-storage.md).
151
+
152
+ ## Project documentation
153
+
154
+ - [Architecture](docs/architecture.md) and [reuse decisions](docs/reuse.md).
155
+ - [Roadmap and implementation limits](docs/roadmap.md).
156
+ - [Interface specifications](docs/interfaces/README.md).
157
+ - [Validation reports](docs/validation/stage56.md), [documentation](docs/validation/stage7.md)
158
+ and [integration](docs/validation/integration.md).
159
+ - [Contributing and local checks](CONTRIBUTING.md).
160
+ - [Git and PyPI release procedure](docs/releasing.md).
161
+
162
+ Distributed under the [MIT License](LICENSE). Third-party test fixtures retain their
163
+ original copyright and license notices.
@@ -0,0 +1,55 @@
1
+ # Architecture
2
+
3
+ `pg_maker` is an independent Python controller. The CLI parses input and displays
4
+ results; `MakerService` owns application operations; workers execute durable jobs.
5
+ The pg_play MCP adapter uses the same service contract through the machine CLI.
6
+ There are no runtime imports from sibling projects.
7
+
8
+ ```text
9
+ src/pg_maker/
10
+ cli.py, api.py CLI and application service
11
+ models.py, documents.py Typed requests, schemas and semantic validation
12
+ errors.py, storage.py Stable errors, strict JSON, hashes, atomic IO and locks
13
+ security.py, progress.py Secret references, redaction and progress logging
14
+ assets.py Idempotent project initialization from package data
15
+ config.py, yamlio.py Strict YAML, effective configuration and provenance
16
+ identity.py Versions, names and installation paths
17
+ development/ Owned Git sessions, patch stacks, iteration CLI
18
+ execution/ Workers, state/events, cancellation, build and recovery
19
+ runners/ Runner protocol and Docker implementation
20
+ planning/ Environment preparation, resolution, locks, DAGs and reuse keys
21
+ sources/ Git/archive/snapshot resolution and content-addressed inputs
22
+ changes/ ChangeSets, application receipts and agent workspaces
23
+ builders/ Autotools and component builders
24
+ packaging/ InstallTree, package roles and DEB output
25
+ validation/ Source, acceptance and installed-package checks
26
+ documentation/ Structural writer, translations, DocBook/Sphinx and theme
27
+ artifacts/ Manifests, output inventory and reports
28
+ integrations/ pg_play/component/v1 machine contract
29
+ schemas/ Schemas for implemented documents
30
+ bundled/ Editable files emitted by init
31
+ recipes/ Platform and PostgreSQL major-version catalogs
32
+ ```
33
+
34
+ `execution` contains process streaming and timeouts, a durable event journal,
35
+ resource ownership, immutable checkpoints, component caches and disk preflight.
36
+ A development iteration creates a new immutable BuildLock/BuildPlan; it does not
37
+ change the inputs of an existing operation. Git checkouts remain private to the
38
+ session and are separate from build scratch directories.
39
+
40
+ ## Extension rules
41
+
42
+ Specify inputs, outputs, failure behavior and an MD contract before adding an
43
+ adapter. Add contract tests at boundaries that can actually vary. `Runner` is a
44
+ protocol because execution backends can be replaced. Built-in implementations use
45
+ explicit registries. Ordinary service functions do not need an abstract base class,
46
+ dependency injection container or automatic plugin discovery.
47
+
48
+ Future adapters can extend source resolution, builders, package formats,
49
+ qualification and publication. The current executable boundary is documented in
50
+ [the roadmap](roadmap.md) and reported by `--component-capabilities`. Placeholder
51
+ module directories do not imply that their adapters are implemented.
52
+
53
+ The build DAG reuses runner/state/process primitives. Infrastructure
54
+ `container_commands` requests remain a separate operation type, with their own
55
+ schema; they must not silently acquire BuildPlan semantics.
@@ -0,0 +1,72 @@
1
+ # Disk use during development
2
+
3
+ Check capacity before a build and after a series of debugging runs:
4
+
5
+ ```bash
6
+ df -h /tmp .
7
+ du -sh /tmp/pg-maker-*
8
+ docker system df
9
+ docker ps -a
10
+ ```
11
+
12
+ Storage grows independently in InputStore, per-feature/language source/object/prefix
13
+ workspaces, documentation output, recovery checkpoints, shared caches, previous
14
+ attempt archives, exported results and Docker images/build cache. `--no-cache`
15
+ disables shared reuse, but keeps private checkpoints for resume.
16
+
17
+ `execution.limits.min_free_disk_bytes` is a free-space reserve checked before steps
18
+ and checkpoint creation. Development snapshot/copy paths also estimate their copy
19
+ size. This is a preflight guard, not a filesystem quota: a compiler or renderer can
20
+ consume additional space within a step. Reserve enough space for expected working
21
+ trees. Prefer a small fixture or documentation-only goal when a full build is
22
+ unnecessary. Database tests remain opt-in.
23
+
24
+ ## Completed operations
25
+
26
+ Check status and owned resources before cleanup. Cancel active operations through
27
+ `pg-maker cancel` and wait for resource release. Export outputs first:
28
+
29
+ ```bash
30
+ pg-maker export operations/RUN --out exported-result
31
+ pg-maker cleanup operations/RUN --export exported-result --out cleanup.json
32
+ pg-maker cleanup operations/RUN --apply cleanup.json
33
+ ```
34
+
35
+ The verified preview targets only `workspace/build`, `workspace/source` and
36
+ checkpoints. Packages, logs and reports remain. Resume is rejected after scratch
37
+ cleanup. Removing InputStore or an image ID referenced by a lock also prevents an
38
+ offline rebuild. Input stores can be shared through `transport.input_store`; inspect
39
+ those references before removing an entire temporary project.
40
+
41
+ ## Development sessions
42
+
43
+ ```bash
44
+ pg-maker dev pin development 000003
45
+ pg-maker dev prune development --keep-last 2 --out prune.json
46
+ pg-maker dev prune development --keep-last 2 --apply prune.json
47
+ ```
48
+
49
+ Current and pinned iterations, working Git trees and patch stacks are retained.
50
+ Old inactive iteration/debug scratch is removed only after the plan is revalidated.
51
+ Locks, reports and input snapshots remain available. Cleaned iterations cannot be
52
+ resumed. Use the separate cache preview/apply operation to reclaim unpinned entries:
53
+
54
+ ```bash
55
+ pg-maker cache prune development/cache --out cache-prune.json
56
+ pg-maker cache prune development/cache --apply cache-prune.json
57
+ ```
58
+
59
+ Completed ordinary operations retain cache pins until their lifecycle cleanup
60
+ releases them. InputStore garbage collection is not automatic.
61
+
62
+ ## Docker storage
63
+
64
+ `docker image prune -a`, `docker builder prune` and `docker volume prune` affect the
65
+ shared Docker daemon. They are manual administrative operations, never pg_maker
66
+ finalizers. Prefer deleting specific unused images after checking saved locks.
67
+ pg_maker removes only containers/resources owned by its operations, including their
68
+ anonymous volumes; named volumes are retained.
69
+
70
+ Historical observation: on 2026-10-17, removing completed stage-4 workspaces reduced
71
+ that temporary directory from about 12 GB to 40 MB, releasing roughly 11 GB. State,
72
+ logs and reports were retained; other projects' Docker images/volumes were untouched.
@@ -0,0 +1,86 @@
1
+ # Developing PostgreSQL and extensions
2
+
3
+ Start with prepared environments, a BuildLock and retained InputStore. Git commands
4
+ operate inside repositories owned by the session. `--repository` copies a local
5
+ PostgreSQL repository with history; the original checkout stays with its owner.
6
+
7
+ ```bash
8
+ pg-maker dev open work --lock example/lock.json
9
+ # Alternative: --from-run /path/to/operations/RUN
10
+ # Preserve local history with --repository /path/to/repository.
11
+ pg-maker dev status work
12
+ ```
13
+
14
+ Status returns `trees.postgresql.source` and paths such as
15
+ `trees.component:pg-wait-sampling.source`. Edit these with an ordinary editor.
16
+ Bundled contrib lives under PostgreSQL's `contrib`; external components have their
17
+ own Git trees. Recipe ID `pg-wait-sampling` differs from SQL name `pg_wait_sampling`.
18
+
19
+ ```bash
20
+ pg-maker dev patch work commit --scope component:pg-wait-sampling --id fix-build
21
+ pg-maker dev explain work --component pg-wait-sampling
22
+ pg-maker dev build work --component pg-wait-sampling --detach
23
+ pg-maker dev status work
24
+ # After the iteration has stopped:
25
+ pg-maker dev exec work --component pg-wait-sampling -- make -n
26
+ pg-maker dev build work --goal package --detach
27
+ ```
28
+
29
+ Build snapshots uncommitted edits too. Editing after startup cannot change that
30
+ iteration's immutable inputs. Package/docs goals use the complete feature;
31
+ documentation must be enabled in the initial lock. Debug execution uses a separate
32
+ copy of the selected iteration's working results. The default is the latest iteration;
33
+ `--iteration 000001` selects another and `--target` selects a platform.
34
+
35
+ Use ordinary status/events/cancel commands with the returned operation_directory.
36
+ Build iterations support ordinary resume; debug commands are repeated as new runs.
37
+ A corrected source tree requires a new `dev build`. Resume retries the original
38
+ operation with its original inputs.
39
+
40
+ ## Patch series
41
+
42
+ ```bash
43
+ pg-maker dev patch work import --patch /path/to/series.json
44
+ # A single patch: --patch /path/to/fix.patch --id fix-name
45
+ pg-maker dev patch work pop --count 2
46
+ # Edit the current patch; refresh replays the remaining series after it.
47
+ pg-maker dev patch work refresh
48
+ pg-maker dev patch work rebase --onto-lock /path/to/new-version-lock.json
49
+ # Resolve conflicting files, then continue:
50
+ pg-maker dev patch work continue
51
+ # Or restore the state before the pending operation:
52
+ pg-maker dev patch work abort
53
+ pg-maker dev patch work export --out patch-series
54
+ ```
55
+
56
+ Each patch has a Git commit. Ordinary Git commits can be imported into the linear
57
+ series with `dev patch adopt`. Pop retains the unapplied tail; push reapplies it.
58
+ An external-component rebase uses `--scope component:ID --onto-source HASH`, referring
59
+ to a snapshot already in the session's InputStore. PostgreSQL rebase uses a new lock
60
+ and requires the same component repository set. Conflicted imports retain the rest
61
+ of the queue. Export writes format-patch files and `series.json`.
62
+
63
+ Before full release qualification, incorporate exported source changes and acceptance
64
+ tests into the regular release configuration and resolve again. Development snapshots
65
+ remain unverified.
66
+
67
+ ## Retention
68
+
69
+ ```bash
70
+ pg-maker dev pin work 000001
71
+ pg-maker dev prune work --keep-last 2 --out cleanup.json
72
+ pg-maker dev prune work --keep-last 2 --apply cleanup.json
73
+ pg-maker cache prune work/cache --out cache-cleanup.json
74
+ pg-maker cache prune work/cache --apply cache-cleanup.json
75
+ ```
76
+
77
+ Prune retains working Git trees, current/pinned iterations, inputs, locks, journals
78
+ and outputs. It removes selected old build/checkpoint/debug scratch and releases
79
+ those runs' cache pins. A separate cache prune can reclaim unreferenced CAS files.
80
+ Global Docker images/volumes and other projects' inputs are untouched.
81
+
82
+ Core or bundled-contrib edits conservatively invalidate PostgreSQL's combined build.
83
+ External components are separate. Core headers/ABI, flags or image changes invalidate
84
+ affected extensions. Verified caches can supply successful results; partial object
85
+ files only accelerate a new make invocation. See [session contract](interfaces/development.md)
86
+ and [recovery](interfaces/recovery.md).
@@ -0,0 +1,32 @@
1
+ # Interface specifications
2
+
3
+ These contracts describe implemented public behavior:
4
+
5
+ - [API and CLI](api.md)
6
+ - [Models and documents](documents.md)
7
+ - [Runner and subprocesses](execution.md)
8
+ - [State, events and cancellation](state.md)
9
+ - [Errors, logs and secrets](observability.md)
10
+ - [Files, hashes and package resources](storage.md)
11
+ - [Machine contract](machine.md)
12
+ - [Configuration and identity](configuration.md)
13
+ - [PostgreSQL major-version catalog](postgresql.md)
14
+ - [Sources and InputStore](sources.md)
15
+ - [Environment preparation](environments.md)
16
+ - [BuildLock and BuildPlan](planning.md)
17
+ - [ChangeSets and agent workspaces](changes.md)
18
+ - [Git sessions, patches and development iterations](development.md)
19
+ - [Default components and their documentation](components.md)
20
+ - [Documentation pipeline](documentation.md)
21
+ - [Build backend, components and test evidence](build.md)
22
+ - [InstallTree, PackageSpec, DEB and installation checks](packaging.md)
23
+ - [Resume, cache, resource guards and export](recovery.md)
24
+ - [Runtime image handoff](runtime.md)
25
+ - [Scratch cleanup](cleanup.md)
26
+
27
+ [Distribution publication](publication.md) is a design boundary with no executable
28
+ adapter yet. Python package publication has a separate [release procedure](../releasing.md).
29
+
30
+ Public behavior changes start with the corresponding MD contract and JSON Schema.
31
+ Document compatibility explicitly. Private helpers need types, docstrings and
32
+ validation at their public caller, rather than a separate specification per function.
@@ -0,0 +1,75 @@
1
+ # MakerService and CLI
2
+
3
+ `api.MakerService(operations_directory: Path)` takes an absolute directory. The
4
+ Python API does not read argparse state or change the working directory.
5
+
6
+ | Method | Input | Result or effect |
7
+ | --- | --- | --- |
8
+ | doctor | None | Local Linux Docker version/architecture; unavailable daemon is a precondition failure |
9
+ | start_operation | Typed request, optional operation/request IDs | Persist input, start worker, return OperationState |
10
+ | status | Absolute operation directory | Read journal state; reconstruct snapshot when the owner is gone |
11
+ | events | Directory, nonnegative cursor, limit 1–1000 | Events, last sequence and has-more flag |
12
+ | cancel | Existing operation | Persist cancellation; clean verified orphan resources |
13
+ | wait | Directory, optional positive timeout | Terminal state; waiting timeout does not cancel the worker |
14
+ | config_show / validate | Manifest and overrides | Effective config/provenance/bindings or validated variants/requirements |
15
+ | prepare_environments / resolve | Manifest and operation options | Durable operation producing EnvironmentManifest or BuildLock |
16
+ | plan | Lock, goal, input store and test override | BuildPlan without downloads, Docker or compilation |
17
+ | build | Lock or saved plan and execution options | Durable build operation |
18
+ | resume / export / artifacts | Operation/result references | Verified retry or portable output references |
19
+ | dev_open / dev_status / dev_patch | Session and patch inputs | Owned Git session and patch stack operations |
20
+ | dev_build / dev_explain / dev_execute | Session and iteration/selection options | New iteration, reuse reasons or durable debug operation |
21
+ | dev_pin / dev_prune | Session, iteration or retention plan | Preserve checkpoints or clean old scratch |
22
+
23
+ ```python
24
+ from pathlib import Path
25
+ from pg_maker.api import MakerService
26
+ from pg_maker.models import CommandSpec, EnvironmentSpec, OperationRequest
27
+ from pg_maker.runners.docker import current_user
28
+
29
+ service = MakerService(Path("/absolute/project/operations"))
30
+ request = OperationRequest(
31
+ EnvironmentSpec("sha256:" + "0" * 64, current_user()), # Use a real local image ID.
32
+ (CommandSpec("kernel", ("uname", "-s"), timeout_seconds=30),),
33
+ )
34
+ state = service.start_operation(request, request_id="check-1")
35
+ state = service.wait(service.directory / state["operation_id"])
36
+ ```
37
+
38
+ Repeated request IDs with identical input hashes return the existing operation,
39
+ including terminal operations. Different inputs produce `precondition_failed`;
40
+ occupied operation IDs produce `ownership_error`. The request registry is locked.
41
+
42
+ Preparation/resolve use the same worker, journal, cancellation and idempotency
43
+ machinery. Inputs contain effective configuration and explicit bindings. Successful
44
+ results contain document path, file SHA256 and semantic document hash. Their
45
+ `--out` is a file; `--operations` selects the operations directory. `plan --out`
46
+ writes JSON; otherwise it returns the document.
47
+
48
+ `build(lock, goal=None, plan=None, plan_hash=None, run_db_tests=None,
49
+ input_store=None, cache_store=None, use_cache=True, operation_id=None,
50
+ request_id=None, components=None, reuse_from=None)` validates and starts BuildRequest.
51
+ A supplied plan determines the default goal; otherwise it is build. The plan must
52
+ match the reconstructed DAG and requested plan hash. Plan
53
+ creation timestamps do not change request idempotency. The plan or lock controls
54
+ the default test mode; explicit overrides must agree with a supplied plan. Changing
55
+ that mode changes plan/input identity.
56
+
57
+ Goals include source/build/package/verified and doc-source/translations/
58
+ translated-docs/docs. Documentation commands use the same build service. Build-time
59
+ feature/mode/documentation flags validate the lock instead of modifying it. Resolve
60
+ again to change the locked configuration; development sessions create new locks for
61
+ code edits. Results record reports, hashes, qualification, database tests, failures
62
+ and publication eligibility. Only full successful qualification can grant eligibility.
63
+
64
+ `runner check` exercises infrastructure commands using an existing immutable image;
65
+ it is not a PostgreSQL build. `--detach` returns after worker startup; otherwise the
66
+ CLI waits. `--machine` always uses the same envelope, including errors.
67
+
68
+ Exit codes: invalid CLI/input 2, failed precondition 3, unsupported 4, partial 5,
69
+ execution failure 6, cancellation 7, ownership 8. Status/events/cancel report the
70
+ success of reading/requesting; operation status is in the result. SIGINT in a waiting
71
+ CLI returns 130 without stopping the worker.
72
+
73
+ New operation types require an input schema and explicit engine dispatch. New CLI
74
+ commands call the same service. See [recovery](recovery.md), [documentation](documentation.md)
75
+ and [development](development.md) for operation-specific contracts.
@@ -0,0 +1,112 @@
1
+ # PostgreSQL and component builds
2
+
3
+ The initial backend is Autotools on Debian 13 / x86_64, with release/debug builds.
4
+ The [catalog](postgresql.md) describes supported majors; the original end-to-end
5
+ build target was PostgreSQL 18.1. `MakerService.build` creates a durable BuildRequest.
6
+ Source only prepares sources. Without a supplied plan, the default goal is build;
7
+ a supplied plan determines the goal unless explicitly overridden. Package, installed
8
+ product harness and resume are implemented. Extended release-validation fixtures
9
+ remain unsupported; build mode release is independently supported.
10
+
11
+ ## Quick mode and full tests
12
+
13
+ `defaults.validation.run_db_tests=false` is the development default. Candidate core
14
+ and components compile/install into a private prefix; expected test inventory,
15
+ check/check-world, component tests/loading, acceptance and baseline are omitted.
16
+ No test clusters are created. Reports say unverified, db_tests=skipped and
17
+ publication_eligible=false. Utility tests are unaffected.
18
+
19
+ `--run-db-tests` or Python true enables the full path; `--skip-db-tests`/false selects
20
+ the quick path. None inherits a supplied plan or locked default. YAML changes require
21
+ resolve. The effective boolean enters BuildPlan and its hash. An explicit flag that
22
+ conflicts with a supplied plan fails before startup. The full evidence adapter currently
23
+ supports PostgreSQL 18; other catalog majors support quick builds/docs only.
24
+
25
+ `execution.build.execute_build(directory, token)` verifies immutable input, lock and
26
+ implementation, reconstructs the selected DAG and compares plan hash. Removing a test
27
+ step cannot preserve qualification. Branches run sequentially in separate containers
28
+ and directories. Candidate receives common plus feature changes; full-test baseline
29
+ receives common changes only. Selected components build in both branches.
30
+
31
+ Full candidate order: sources → changes → integrated source components → configure →
32
+ make → private prefix install → expected test inventory → check → world-bin →
33
+ install-world-bin → check-world → components/tests → acceptance → report. Baseline
34
+ runs core check and component/acceptance checks without check-world, recording
35
+ source_test_scope=baseline-core. Acceptance without baseline expectations is candidate-only.
36
+
37
+ Configure checks requested settings against Makefile.global/pg_config.h before compile,
38
+ rejects unrecognized options and records its result. Compiler warnings are inventoried;
39
+ a general warnings-as-errors filter is not implemented. Plans record argv/env/user/cwd,
40
+ limits and timeouts; commands generated by native steps are recorded under branch
41
+ output/commands.
42
+
43
+ ## Builders and components
44
+
45
+ `builders.autotools` contains validate_build, extra_tests, expected_inventory,
46
+ reconcile and required-test validation. Queries execute Make inside the container.
47
+ A new backend needs a module, explicit dispatch, supported-settings schema and real
48
+ source validation, not a plugin framework.
49
+
50
+ Component integration copies source-tree inputs into unused source directories;
51
+ overwriting existing PostgreSQL files requires a ChangeSet. Component build executes
52
+ explicit make/install targets, with native/cluster tests only when enabled. Each
53
+ component has a separate build_tools or build_and_test_tools step. A quick component
54
+ reports built=true and tests=skipped, never passed.
55
+
56
+ | Type | Build behavior |
57
+ | --- | --- |
58
+ | contrib | Selected PostgreSQL directory, explicit Make targets and optional load checks |
59
+ | source-tree | Separate input copied into an unused source directory, then Make |
60
+ | pgxs | Separate sources, USE_PGXS=1 and the exact private-prefix PG_CONFIG |
61
+ | utility/library | Make; optional configure with prefix and explicit test targets |
62
+
63
+ Full-test external components must declare test_targets. PGXS/contrib/source-tree
64
+ REGRESS/ISOLATION/TAP inventory is collected before tests and reconciled afterward;
65
+ empty inventory is not success. Build systems are not guessed. SQL extensions,
66
+ shared libraries and preload settings are checked in fresh clusters. Internal
67
+ headers/PGXS/ecpg support compilation but are excluded from distribution payloads.
68
+
69
+ ## Evidence and acceptance
70
+
71
+ TAP is always configured and cannot be disabled by feature arguments. Full mode
72
+ inventories configured SUBDIRS, REGRESS, ISOLATION, schedules and ECPG check.
73
+ Check-world remains required for smoke qualification. OpenSSL enables ssl and
74
+ libpq_encryption extras. GSSAPI/LDAP/OAuth and the extended release-validation profile
75
+ require additional service fixtures and are explicitly unsupported when requested.
76
+
77
+ TAP::Parser records each Perl script's plan, executed/failed/skipped assertions,
78
+ exit/wait and skip_all. Unknown skip-all, empty or missing suites fail. Allowed
79
+ not-applicable suites are declared in inventory before execution. Ordinary assertion
80
+ SKIPs remain recorded. Successful PostgreSQL removes regression.out, so regression
81
+ evidence comes from complete stdout grouped by make --output-sync=target, with
82
+ name/count/TAP-plan reconciliation. Original logs, failure diffs and TAP logs remain.
83
+ Configure/compiler warnings are recorded per step.
84
+
85
+ Acceptance uses fresh PGDATA, private-prefix initdb/pg_ctl/psql, bounded readiness
86
+ and ON_ERROR_STOP. Configuration and server.log live in PGDATA. SQL scripts are
87
+ UTF-8 SQL; command scripts are YAML argv arrays without shell interpretation.
88
+ Equals compares complete trimmed stdout; booleans map to psql t/f. Successful scripts
89
+ have SQLSTATE 00000. Explicit SQLSTATE assertions may accept psql exit 3 with verbose
90
+ stderr evidence; connection errors, timeouts and missing SQLSTATE remain failures.
91
+ Prefix substitution works before and after packaging. Baseline assertion-failure
92
+ is accepted only for the one named assertion ID.
93
+
94
+ Required tests resolve to actual evidence IDs: acceptance ID, component.make-target,
95
+ source/directory/regression-test or TAP script path. Skipped TAP cannot satisfy them;
96
+ unknown IDs fail. Source builds grant at most source-verified and never publication
97
+ eligibility. Quick/source-only runs remain unverified. Reports contain receipts,
98
+ steps, counts, expectations, warnings and private prefix paths.
99
+
100
+ ## Execution and distribution continuation
101
+
102
+ The non-root build user must match host mount ownership; environment preparation
103
+ creates its passwd/group entries. The prefix is mounted below /opt only inside the
104
+ container. Networking is off; memory/swap/CPU/shared memory are limited. Worker
105
+ journal/process cleanup/cancellation are shared infrastructure. Keep-failed-environment
106
+ retains only a stopped owned container, removable through cancel.
107
+
108
+ Package uses InstallTree/PackageSpec/DEB. Verified adds isolated installation checks
109
+ and can grant package-verified. Successful matrix branches survive failures elsewhere;
110
+ partial reports list failures and return 5. Test steps are not ordinary cache hits.
111
+ Command log references are relative to branch output and travel with caches/exports.
112
+ See [packaging](packaging.md), [recovery](recovery.md) and [development](development.md).
@@ -0,0 +1,58 @@
1
+ # Source changes
2
+
3
+ `changes.loader.load_changes(references, base, version)` and `load_components(...)`
4
+ validate documents, compatibility, requires/conflicts, unique IDs/revisions and
5
+ explicit files. Stable topological order preserves available independent-node order.
6
+ Operations and acceptance scripts have logical input names and hashes; resolve copies
7
+ them into InputStore. Required tests merge without allowing different acceptance
8
+ checks to share an ID.
9
+
10
+ `changes.apply.apply_changes(source, feature, lock, store, branch, receipts, check)`
11
+ applies changes; check observes cancellation. Each group works on a separate tree
12
+ copy and publishes only after every operation and postcondition succeeds. Receipts
13
+ record input/output hashes, diff, changed paths and applied/already_satisfied status.
14
+ Already-satisfied is limited to the built-in socket patch's exact result.
15
+
16
+ Resolve creates the common patch against current sources. The target full-line
17
+ socket definition uses `/var/run/postgresql` and a comment describing shared server/
18
+ libpq use. Existing configured lines are normalized to this representation; repeating
19
+ the exact result does not change the tree.
20
+
21
+ Groups and operations preserve explicit ordering. UTF-8 unified patches apply without
22
+ shell, offsets or fuzz. Supported inputs include diff -u, git diff and git format-patch,
23
+ with regular-file additions/deletions (100644/100755). Existing-file mode changes,
24
+ binary changes, rename/copy and symlink patches are unsupported in this strict
25
+ release ChangeSet adapter. The development Git stack has a separate Git-based adapter.
26
+
27
+ Text insertion verifies cardinality, top/bottom order, context and optional input
28
+ hash. Each top matches the first bottom before the next top; unrelated later table
29
+ markers do not introduce ambiguity. Repeated insertion without a receipt fails.
30
+ Changes cannot escape the source tree or traverse symlinks. Successful publication
31
+ removes temporary source.before-N copies. Failure/cancellation preserves original
32
+ inputs and never reapplies a partially modified group.
33
+
34
+ New actions require explicit registry entries, versioned schemas and positive/negative
35
+ fixtures. The only built-in source patch unifies the Unix socket directory; branding
36
+ is explicit data.
37
+
38
+ ## Agent workspaces
39
+
40
+ `changes.workspace.workspace(input_store, source_hash, destination)` copies a
41
+ verified snapshot into a new destination/source and writes workspace.json. It checks
42
+ source size plus a 4 GiB reserve and never hardlinks CAS. `export_changes(directory,
43
+ output, id, postgresql)` compares against the verified base and emits ChangeSet plus
44
+ unified diff. UTF-8 additions/deletions/edits, including no-final-newline files, are
45
+ supported. Binary/symlink/mode changes are rejected. New file permissions follow umask
46
+ when applying; empty directories do not appear in diffs.
47
+
48
+ `validate_changes(file)` validates schema/referenced operation files and returns
49
+ hashes with acceptance_executed=false. Export does not assert ABI/data/WAL compatibility;
50
+ all remain unknown until separately specified and tested.
51
+
52
+ With `workspace(..., lock=BuildLock, feature=ID)`, the base includes common and existing
53
+ feature changes, stored as a separate CAS tree. `until="CHANGE_ID/OPERATION_ID"` stops
54
+ before an operation for adapting it. Insert the resulting diff at that position;
55
+ do not blindly append it. Without a lock, basis remains raw upstream. Export verifies
56
+ the frozen base independently of later lock-file edits. Validation also checks
57
+ insertion schemas and acceptance script hashes/existence; execution is separate.
58
+ CLI workspace/export/validate and pg_play MCP share these fields.