Domain-graph worker for the modernize archetype. Groups the estate's Louvain communities into business domains, attaches each requirement to its cluster (advisory cluster_id provenance), and invokes wicked-core's domain-graph build (which reads the annotated estate store, recomputes coverage fail-closed, and builds the requirements graph) — then validates core's output against the vendored schema. Use when: dispatched by wicked-garden-domain after rule extraction to turn a flat rule set into cluster-keyed domains; "group these into domains", "build the requirements graph", "translate clusters into a domain model". NOT for mining the rules themselves (that is domain-extractor) or threat-modeling (that is domain-coverage).
Install
npx skillscat add mikeparcewski/wicked-garden/wicked-garden-domain-modeler Install via the SkillsCat registry.
Modernize Translator
You turn a flat set of extracted rules into a cluster-keyed domain model
and invoke core's domain-graph build to produce the requirements graph. A domain
is derived from an estate Louvain community, not hand-partitioned.
Contract you emit against
Same vendored domain-model@1.0.0 schema as the extractor. Your domains{}
grouping — each domain groups the requirements whose components fall in one estate
community, carries an advisory cluster_id (the Louvain index), and declares itsentities{} — is advisory provenance. The authoritative requirements graph is
built by core from the annotated store (core derives domains from estate's
communities). You invoke core, you don't reimplement it.
The loop
- Read clusters from estate — the full-membership feed
clusters --json --summary→[{id, size, members:[symbol_id], …}], viaestate_client(db).read_clusters()(CLI) or_mocks.EstateClient(hermetic).
On the real path this is informational (core derives the authoritative
domains when it builds the graph); the id is a volatile positional index, so
key durable grouping on a hash of the sorted member set, not the raw id (record
the raw id only as advisorycluster_id). - Assign each requirement to a domain by the community its
legacy_components[]SymbolIds belong to (advisory grouping / provenance for
the antagonist). A requirement whose components span communities goes to the
dominant one; note the split. - Invoke core's domain-graph build.
core_client().domain_graph(db, out)
shellswicked-core domain-graph --db <db> --out requirements_graph.json,
which reads the annotated store, recomputes front-half coverage, and buildsrequirements_graph.json(a capability plan, not a code skeleton). It fails
closed (writes nothing, non-zero exit) if coverage < 1.0 — every
behavior-bearing node must already be annotated (the extractor's job). There is
no doc handed in and no--overlay: the store is the input. Whencore_client()isNone(no peer), fall back to the hermetic lane —emit_domain_model.pyassembles the doc and_mocks.BrainClientstands in. - Validate core's output. Cross-check the built
requirements_graph.json
withscripts/domain/validate_domain_model.py(schema + hard invariants)
before returning.
Invariants you must not break
domainsis required; every domain hasrequirementsandentities.cluster_idis advisory provenance only — never authoritative. estate is
the sole owner of graph structure; you reference it.- No silent drop: a requirement dropped from a domain needs
disposition:"drop"
and adisposition_reason, or it counts against coverage. metadata.migration_mode ∈ {structural, functional}—functional
(capability-grouped) is the default;structuralis 1:1.
What is wired vs stubbed
The estate clusters read and core's domain-graph build are wired to the
live CLIs via scripts/domain/_clients.py (estate_client / core_client),
falling back to _mocks.py when the peers are absent. The grouping heuristic
(community → domain) and the schema validation are real. The real end-to-end
build additionally needs a fully-annotated, INDEXED store (coverage == 1.0) to
clear core's fail-closed gate — that store-seeding is the end-to-end milestone
(core#28), not this worker. Full field map:
the wicked-garden-domain skill's refs/domain-model-emit.md.