Skip to content

feat(op): the graph document carries its catalog — mandatory even empty, refused when absent - #593

Merged
David-Noble-at-work merged 1 commit into
developfrom
graph-carries-the-catalog
Aug 21, 2026
Merged

David-Noble-at-work merged 1 commit into
developfrom
graph-carries-the-catalog

Conversation

@David-Noble-at-work

Copy link
Copy Markdown
Contributor

Phase 1 of resource-construction —
4-resource-management.md §5.4 implemented.

The section

graphData gains a mandatory resources section — every current-generation entry as intent
({id, uri, state: "pending"}, append order, via the new ResourceCatalog.IntentEntries); content-addressed
entries additionally carry packed bytes as before. Present even when empty; outside the canonical bytes like
the content section.

The gates

  • LoadGraph refuses a document without the section — every pre-ruling document fails to load and is
    re-planned; schema_version stays 1 by ruling.
  • unpackCatalog (replacing unpackContent): rows restore as Pending with recorded ids — the
    trace-rehydrate discipline; unpackers consume matching content blobs; an orphan blob errors; nextID
    re-derives.
  • Executor backstop: a catalog-less graph fails pre-flight (preflight_failed) before any dispatch, in
    Run and ResumeUnwind both.
  • ResourceState serializes as its name — "pending", never a bare ordinal (the mode: 384 lesson,
    applied at the type).

The judgment pins land green — early

The plan predicted the flip at phase 3; it arrived with phase 1, because planning already interns the
resource-typed source — serialization was the missing half, and the destination's absence (a product is a
runtime fact) was already true. Both pins now assert the ruled contract in both directions:

  • pkg/op/provider/plan/catalog_contract_test.go — source pending present, destination absent,
    against the reloaded document
  • cmd/devlore-test/devloretest/data/test_graph_catalog_contract.star — the same, front to back through the
    harness: 6 expectations, passing

Plus four new §5.4 pins: empty-section round trip (byte-identical), missing-section refusal, id-preserving
intent-row reconstruction, executor backstop.

Verified

  • make check — 103 packages ok, 0 failures — the tree is fully green, pins included
  • make vet GOOS=windows, GOOS=linux
  • Windows expectation: identical to baseline 3, name for name

Closes #583. Refs #581, #444. Phase 3's remaining substance (pending-only claiming with no plan-time
existence I/O; the promise grammar) is recorded in the plan.

…pty, refused when absent

Phase 1 of the resource-construction plan (4-resource-management.md section 5.4). The graph document gains a
mandatory resources section: every current-generation ledger entry as intent -- id, uri, state pending, in
append order, via the catalog's new IntentEntries -- with content-addressed entries additionally carrying
their packed bytes as before. The section serializes even when empty and sits outside the canonical bytes,
like the content section.

LoadGraph refuses a document without the section: every pre-ruling document fails to load and is rewritten by
re-planning, with schema_version staying 1 by ruling. unpackCatalog replaces unpackContent as the load-side
dual: every row restores as a Pending entry with its recorded id (the trace-rehydrate discipline -- interning
disabled, constructors rebuild from the URI's specific, unpackers consume matching content blobs), an orphan
content blob is an error, and nextID re-derives from the recorded ids. The executor backstops the same rule:
a catalog-less graph fails pre-flight with preflight_failed before any dispatch, in Run and ResumeUnwind
both.

ResourceState learns to serialize as its name -- a document carries "pending", never a bare ordinal -- the
same typed-value rule the mode-as-384 rendering violated.

Both judgment pins land green with this change, earlier than planned: the plan expected them to flip with
phase 3, but planning already interns the resource-typed source, so serialization was the missing half and
the destination's absence -- a product is a runtime fact, not intent -- was already true. The pins now assert
the ruled contract in both directions: source present as pending, destination absent, from Go
(catalog_contract_test.go) and front to back through devlore-test (test_graph_catalog_contract.star, six
expectations, passing). Four new section-5.4 pins cover the empty-section round trip byte-identically, the
missing-section refusal, id-preserving intent-row reconstruction, and the executor backstop.

Verified with make check (103 packages ok, 0 failures -- the tree is fully green, pins included) and make vet
under GOOS windows and linux.

Closes #583. Refs #581, #444.
@David-Noble-at-work David-Noble-at-work self-assigned this Aug 21, 2026
@David-Noble-at-work
David-Noble-at-work merged commit 133e893 into develop Aug 21, 2026
7 of 8 checks passed
@David-Noble-at-work
David-Noble-at-work deleted the graph-carries-the-catalog branch August 21, 2026 01:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serialize the catalog section — mandatory even when empty; hard-fail load and pre-flight without it

1 participant