Skip to content

Commit 5cd501b

Browse files
David-Noble-at-workDavid Noble
andauthored
docs(design): the resource-construction rulings become the resource-management body; sketches retire (#592)
Phase 0 of the resource-construction plan. 4-resource-management.md absorbs the 2026-08-20 rulings as body: new section 5, "The Catalog Travels with the Graph" -- intent-only plan-time claiming (string values mint pending entries, promises record promises, products are runtime facts), git-model plan-space paths with the home/system late-binding examples, rel identity with activation that never changes it, the mandatory serialized section with hard load and pre-flight failure, and the graph-intent/trace-observation split. Section 4 rewrites to runtime-only shadowing -- plan-time output claims and implicit same-URI edges are superseded; ordering is the promise's job, and sections 1 and 2 now say so -- with the two-path reconciler absorbed from the catalog-reconciler sketch as 4.1. Appendix A is deleted as rejected, recorded in the resolved decisions alongside the four new rulings. 4.1-resource-identity.md amends the file scheme: catalog identity is the slash-canonical root-relative path; the RFC 8089 absolute form survives only as the rendered form against a bound root; the buildURI sketch follows. 3.6 gains the dispatch-convergence law distilled from the stack-comparison sketches, in current names -- their line-level stacks described a shape that no longer exists. The package-signatures sketch relocates verbatim to 7-registry-knowledge as LorePackaging material. The transport plan's step 3 is annotated: the reference-entry exclusion is withdrawn; the content transport it landed is unchanged. Four stale cross-references to pre-rewrite section numbers are corrected in passing. All five sketches retire: mined, integrated, deleted. The status companion records that the DESIGN now leads the TREE -- the two red judgment pins measure the gap until #583-#586 land. Closes #582. Refs #581, #444. Co-authored-by: David Noble <[email protected]>
1 parent 84771f6 commit 5cd501b

16 files changed

Lines changed: 491 additions & 681 deletions

‎docs/architecture/1-system-model.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ What survives — and matters — from the four-phase picture:
110110
1. **Verify is the truth gate.** A verification step's recorded result (e.g. "port 80 responsive") is what
111111
distinguishes this model from traditional configuration management: the record captures verified facts, not just
112112
"success." Observations — point-in-time resource facts (`file.observe`, `git.observe`) — ride the trace as
113-
results ([4](4-resource-management.md) §6.1).
113+
results ([4](4-resource-management.md) §3, observations).
114114
2. **Every completed step can be undone.** The classical (A, C, S) tuple maps onto the landed compensable-action
115115
contract: forward method, `Compensate<Name>` companion, and the **receipt** as S — captured per dispatch, pushed
116116
on the recovery stack, unwound LIFO on failure ([2.2](2.2-phase-execution.md) owns the contract in full).

‎docs/architecture/2.7-control-plane.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Both the event stream and the hook seam pre-date the control plane, and the firs
4646
`LifecycleHook`, and leave narration orthogonal.
4747

4848
**Terminology.** `Observation` is a settled domain term — a point-in-time **resource fact** (`op.ObservationBase`, the
49-
result of an observe action; [`4-resource-management.md`](4-resource-management.md) §6.1). It is **not** the event
49+
result of an observe action; [`4-resource-management.md`](4-resource-management.md) §3, observations). It is **not** the event
5050
stream: observations flow *through* events as results, and the outbound structured channel is **events**, never
5151
"observations."
5252

‎docs/architecture/3.1-provider-loading.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
> **lifetime half is design that did not land as written**: the `LifetimeStateless` / `LifetimePhase` /
66
> `LifetimeSession` taxonomy and the descriptor-based Registration Examples (`op.Announce(&…{})` / `InitAll`) have
77
> no tree presence — the landed lifetime model is environment-scoped construction (a provider is built against its
8-
> `*op.RuntimeEnvironment` and cached on it; [4-resource-management.md](4-resource-management.md) §7), and
8+
> `*op.RuntimeEnvironment` and cached on it; [4-resource-management.md](4-resource-management.md) §8, provider lifecycle), and
99
> registration is announce-with-metadata ([3-operation-namespaces.md](3-operation-namespaces.md),
1010
> [4.3](4.3-resource-registration.md)). **The full rewrite is recorded step-51 residual debt** (gate finding 1) —
1111
> read the lifetime sections below as an unrealized proposal until then.

‎docs/architecture/3.6-method-classification.md‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,25 @@ configurable per runtime so a hermetic runtime renders without it.
140140
**`plan` is mandatory for planning and not pure** — `LoadDefinition` reads a graph from disk. Either the
141141
planning runtime admits `plan` on separate grounds, or that method moves out of the provider.
142142

143-
## 6. Open questions
143+
## 6. The two dispatch stacks converge in `op.Convert`
144+
145+
Distilled from the retired stack-comparison sketches (2026-08-20; their line-level stacks described a
146+
superseded shape — `NodeBuilder`/`task_builder.go` no longer exist — but the law they proved still holds and
147+
is worth keeping):
148+
149+
**Both dispatch modes bottom out in `op.Convert`'s single seven-step cascade** (assignable/convertible →
150+
slice recursion → map recursion → `SourceConverter` → `TargetConverter` → registered resource construction →
151+
error). Immediate mode (`goReceiver.dispatch`) unpacks Starlark values to natural Go and converts per
152+
parameter inside `Method.Invoke`, at dispatch time. Plan mode (`ActionPlanner.Plan`) converts at
153+
slot-binding time. There is no duplicate type-matching anywhere — one cascade, two entry points.
154+
155+
**The asymmetry that remains is deliberate**: plan mode converts at slot-fill so the catalog can intern
156+
resources before the node is sealed; immediate mode converts at dispatch because immediate receivers pass
157+
raw values and cataloged resources are a planning concern
158+
([4-resource-management.md](4-resource-management.md) §9 item 3). Same cascade, different timing — the
159+
timing difference *is* the plan/immediate distinction, seen from the converter.
160+
161+
## 7. Open questions
144162

145163
1. **Does `query` belong in immediate scope at all?** It is what makes planning non-hermetic today. Excluding it
146164
entirely is simpler than a policy dimension, at the cost of `file.exists` during planning.

‎docs/architecture/4-resource-management.md‎

Lines changed: 134 additions & 68 deletions
Large diffs are not rendered by default.

‎docs/architecture/4-resource-management.status.md‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22

33
**Architecture document:** [4-resource-management.md](4-resource-management.md)
44

5-
**State:** rewritten 2026-07-22 (phase-8 step 51, slice 3). The migration-era body — string-parameter "today"
5+
**State:** rewritten 2026-07-22 (phase-8 step 51, slice 3); **revised 2026-08-20 onto the
6+
resource-construction rulings** ([plan](../plans/resource-construction.md), feature #581): §5 "The Catalog
7+
Travels with the Graph" added (intent-only claiming, git-model plan-space paths, rel identity with run-bound
8+
fsroot, mandatory serialized section with hard pre-flight, graph=intent/trace=observation); §4 rewritten to
9+
runtime-only shadowing with the two-path reconciler as §4.1 (absorbed from the retired
10+
catalog-reconciler-logic sketch); §1/§2 corrected — ordering is the promise's job, never URI matching;
11+
**Appendix A deleted as rejected** (products are runtime facts). The DESIGN is current; the TREE still
12+
carries pre-ruling behavior until #583–#586 land — the two red judgment pins
13+
(`catalog_contract_test.go`, `test_graph_catalog_contract.star`) measure that gap. The migration-era body — string-parameter "today"
614
snapshots, per-method signature-migration tables, `Tombstone` recovery, the `RegisterConstructor` /
715
`coerceSlotValue` coercion chain, the phase-by-phase bookkeeping — is replaced by the landed model: the catalog
816
surface (tree-verified method by method), the `ResourceState` machine and behavior matrix (the 2026-07-14 rulings,
@@ -21,7 +29,7 @@ post-dispatch shadowing for monadic outputs) is named beside it.
2129
| `ResourceState` machine + behavior matrix + `VerifyExistence` pre-flight | Landed (steps 22/41; per-type rollout staged — `file` proven) |
2230
| Observations as results, never catalog members | Landed (ruled 2026-07-14; step 22) |
2331
| Receipts + recovery site (Tombstones retired) | Landed (steps 40/42; [3.5.4](3.5.4-file-provider.md)) |
24-
| Declared output specs (Appendix A) | **Not implemented** — preserved as design |
32+
| Declared output specs (former Appendix A) | **Rejected 2026-08-20** — removed; products are runtime facts |
2533
| Document rewrite onto the landed model | Complete 2026-07-22 (step 51 slice 3) |
2634

2735
## Document Discrepancies
@@ -31,7 +39,10 @@ proposal explicitly.
3139

3240
## Outstanding Work
3341

34-
1. The staged per-type `Resolve`/`Exists` rollout (step 22's ledger).
35-
2. Remote-execution filesystem abstraction (open question §9.1).
42+
1. The resource-construction implementation, #583–#586: serialize + enforce the catalog section; rel
43+
identity + authoring migration; plan-time claiming; run time consumes the catalog. The design in §5 leads
44+
the tree until they land.
45+
2. The staged per-type `Resolve`/`Exists` rollout (step 22's ledger).
46+
3. Remote-execution filesystem abstraction (open question §10.1).
3647
Remaining step-51 slices are tracked in
3748
[step 51](../plans/extract-starlark-from-op/phase-8/steps/51-documentation-debt.md).

‎docs/architecture/4.1-resource-identity.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ inline, so no data is lost at the node level.
179179

180180
| Scheme | Form | URI Examples | Notes |
181181
|---|---|---|---|
182-
| `file` | Hierarchical | `file:///etc/foo`, `file:///usr/local/bin/jq` | [RFC 8089](https://datatracker.ietf.org/doc/html/rfc8089). Empty authority, absolute path. |
182+
| `file` | Opaque (catalog identity) / Hierarchical (rendered) | catalog: `file:etc/foo` — the slash-canonical **root-relative** path; rendered against a bound root: `file:///etc/foo` | **Amended 2026-08-20** ([resource-construction](../plans/resource-construction.md)): catalog identity is the rel — the fsroot is a run parameter, so no volume, home layout, or separator variance enters identity; a plan-authored leading slash anchors at the fsroot (git model) and normalizes away. The [RFC 8089](https://datatracker.ietf.org/doc/html/rfc8089) absolute form survives only as the *display/rendered* form once a run binds the root. |
183183
| `pkg` | Opaque | `pkg:brew/jq`, `pkg:deb/curl`, `pkg:winget/Microsoft/VSCode` | [purl](https://github.com/package-url/purl-spec)-compliant, **versionless** — the catalog URI omits `@version` (version is state, see [§3.4](3.4-platform-package-managers.md)). `Purl()` may append the requested `@version` for display, so `URI()`/`Purl()` converge only on the versionless coordinates. |
184184
| `svc` | Opaque | `svc:nginx`, `svc:postgresql` | Service name. Fragment reserved for future instance disambiguation (e.g., `svc:postgresql#port-5433`). |
185185
| `appnet` | Opaque | `appnet:https%3A//example.com/path` | Wraps an inner URI with targeted escaping (`#` and `?` escaped). Renamed from `net`. |
@@ -207,9 +207,11 @@ calls. Each type builds its URI from its own fields using whatever
207207
logic fits its scheme.
208208

209209
```go
210-
// file: RFC 8089 — hierarchical, empty authority, absolute path
210+
// file: catalog identity is the slash-canonical root-relative path (amended 2026-08-20 — the fsroot is a
211+
// run parameter, so identity carries no volume, home layout, or separator variance; the RFC 8089 absolute
212+
// form is the rendered form against a bound root, never the identity).
211213
func (r *Resource) buildURI() string {
212-
return "file://" + r.SourcePath // SourcePath is always absolute
214+
return "file:" + r.SourcePath.Rel() // rel is the half that serializes
213215
}
214216

215217
// pkg: purl-compliant opaque URI — VERSIONLESS catalog identity.

‎docs/architecture/6-execution-topology.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ runner and UI/API consumers.
520520
> `ControlPlane.Subscribe` / `emit` ([`2.7-control-plane.md`](2.7-control-plane.md), see its
521521
> [Framing](2.7-control-plane.md#framing-three-orthogonal-pieces)); the integration builds the event stream on **this**
522522
> spec, fed from a `LifecycleHook`, and splits it off the command surface. An observe action's `Observation` — a
523-
> resource fact ([`4-resource-management.md`](4-resource-management.md) §6.1) — rides this stream as an event
523+
> resource fact ([`4-resource-management.md`](4-resource-management.md) §3, observations) — rides this stream as an event
524524
> **result**; "observation" stays the resource-fact term, "events" is this channel. This §Telemetry pipeline is the
525525
> remote-transport instance of the app-agnostic eventing bus designed in
526526
> [`2.8-eventing-infrastructure.md`](2.8-eventing-infrastructure.md).

0 commit comments

Comments
 (0)