semantius-optimizer Skill
Closes the reverse arc of the spec lifecycle. It is the fifth peer of the
semantius-* family (architect / analyst / modeler / use-semantius): the only one
that runs the pipeline backwards, from live catalog to *-semantic-spec.md.
semantius-architect → semantius-analyst → semantius-modeler → (users customize / build in the UI) → semantius-optimizer → …
The *-semantic-spec.md this skill produces is interchangeable with one the
semantius-analyst skill writes: same front-matter keys, same section structure
(§1 Overview … §9 Governance), same reconciliation annotations. The
semantius-modeler can re-deploy it; the analyst can audit or extend it. That
compatibility is the point: without it, a module built directly in the Semantius
UI (or customized live) has no spec, and nothing in the pipeline can govern it.
Primary use case: a module exists in production with no spec (built in the UI,
or drifted from its original). This skill produces the missing *-semantic-spec.md
from live state, which then feeds semantius-analyst Extend/Audit or a
semantius-modeler re-deploy.
Division of responsibility
- This skill owns the workflow: pick the module, run the deterministic extractor, present the result, and audit it only if the user later asks.
references/spec-extract-lib.tsowns the mapping: it is the single deterministic source of the generated markdown. All live→spec rules live there, not in prose, so the output is reproducible and every rule is one place.use-semantiusowns the platform contract (thesemantiusCLI, PostgREST encoding, the built-ins list).- This skill is READ-ONLY against Semantius. It never writes to the platform.
Any fix is applied to the
.mdonly; a re-deploy viasemantius-modeleris how changes reach the live catalog.
Writing conventions (every output this skill produces)
- US English spellings, always (optimize not
optimise, behavior notbehaviour, modeling notmodelling, canceled notcancelled). Prefer the-ize/-or/-erform. - No em-dashes (
—). Use(...), a comma, or split sentences. En-dash and hyphen in ranges/compounds are fine. - Singular-subject grammar in prompts ("Looks good?" not "Look good?").
Schema compatibility
This skill writes files at version: "5.4" (the analyst's CURRENT_VERSION; the
SPEC_VERSION constant in spec-extract-lib.ts). The semantius-modeler carries
an EXPECTED_MAJOR and rejects a mismatched major, so the constant must track the
analyst. A major analyst bump (section renumber, table-shape change, new required
key) forces a coordinated update of the analyst template, this skill's extractor,
and the modeler.
The authoritative output shape is
semantius-plugin/skills/semantius-analyst/references/semantic-spec-template.md.
Read it before changing the extractor.
Step 0: Load required context
Read first:
<skills-root>/use-semantius/SKILL.mdand<skills-root>/use-semantius/references/data-modeling.md(built-ins list, platform constraints).<skills-root>/semantius-analyst/references/semantic-spec-template.md(the output template the extractor targets).references/spec-extract-lib.tsin this skill folder (the mapping).
High-level workflow
1. Pick module → 2. Pre-flight the output path, then run the extractor → 3. Present + verify → (4. Audit, only if the user later asks)
Communicating during the run — work quietly; the report is the deliverable
This is deterministic, mostly mechanical work. On the happy path the user should see only three things: (1) the module-picker table, if the module is ambiguous or was not named; (2) the overwrite question, if the output file already exists; (3) the final report (Stage 3). Nothing else.
Do NOT narrate the steps or explain internal mechanics between tool calls. The tool-call chips already show progress, so prose like the lines below — every one of them taken from a real run — is pure noise. Never write anything of this kind:
- "The skill is symlinked to
semantius-plugin/skills/semantius-optimizer." - "The canonical output path does not exist yet, so it's free to write."
- "
bun 1.3.12is available." - "Running the extractor now (no
--forceneeded since the file doesn't exist)." - "The manual filter didn't apply, but the extractor uses the correct shape internally."
The stage names in this workflow are internal structure — never announce "Stage 1", "Stage 2a", etc. Load the required context, pre-flight the output path, and run the extractor silently. If the module was named and unambiguous, hand its slug straight to the extractor — it fails fast with a clear error on an unknown slug, so a separate confirmation read is optional; don't perform one just to have something to report. The next words the user reads after their request should be the Stage 3 report itself.
Stage 1: Pick the module
If the user named a module, use its slug directly. Otherwise list candidates:
semantius call crud read_module '{"order": "module_name.asc"}'
Present module_name, module_slug, module_type, access_scope as a compact
table and ask which to extract. Never guess when several match. Never create a
module here (read-only).
Stage 2: Run the extractor
Stage 2a: Pre-flight, never overwrite silently
BEFORE doing any work, check whether the output file already exists:
test -f semantius/specs/<module_slug>-semantic-spec.md && echo EXISTS || echo FREE
(PowerShell: Test-Path semantius/specs/<module_slug>-semantic-spec.md.)
FREE (does not exist): go to Stage 2b and write it.
EXISTS: STOP and ask the user which they want, then wait for the answer:
- Replace the existing file.
- Save under a different name (the user supplies one, or you suggest an
unused path such as
<slug>-semantic-spec-2.md). - Stop and change nothing.
Do not guess and do not proceed until the user picks. This check is up front on purpose: the extractor must never do a run's worth of reads and then clobber a file, and it must never replace an existing file without an explicit yes.
Stage 2b: Run
bun run references/spec-extract-lib.ts <module_slug> <chosen_outfile>
Pass the path the user chose. Add --force ONLY when the user chose Replace;
without --force the script refuses to overwrite. The script applies the same guard
itself, and it checks the output path first, before any live read, so a direct
invocation also fails fast instead of doing work and then clobbering.
The script reads module, entities (creation order), fields (field-order, auto- fields stripped), permissions, roles, and permission hierarchy; discovers referenced built-ins; and writes the spec. It prints a one-line summary (entity / permission counts). It is idempotent and side-effect-free against the platform.
If bun is unavailable, node also runs it (the script uses only Bun.spawn /
Bun.write; on plain Node, invoke via bunx or install bun; do not hand-port the
mapping into prose, that reintroduces the non-determinism this design removes).
Stage 3: Present and verify
The deliverable is a SHORT, human-facing report — roughly 6-10 lines. The reader asked for a spec; answer the three questions they actually have, in order:
- Did it work, and where's the file? One line, with the path as a clickable link.
- How far can I trust it? One sentence: the spec mirrors the live module, so everything the platform stores (entities, fields, relationships, enums, permissions, roles) is faithful.
- What must I fix by hand? A short list — usually 2-4 items — of things the live module doesn't store, so they couldn't be recovered. Phrase each as a plain to-do about the spec.
Close with one line pointing anyone who wants the missing content authored properly
at semantius-analyst Extend mode.
Write it for the reader, not the pipeline. Do NOT put any of this in the report: stage numbers, the labels "Category A/B", "byte-compatible", "reverse pass", "canonical order", "reconciliation annotations", "the modeler can re-deploy / the analyst can audit", a dumped list of frontmatter keys, or a "trust these" enumeration of every faithfully-copied section. That vocabulary is internal; reciting it is the noise this section exists to prevent. If the report runs long, it is narrating machinery — cut it.
Worked example of a good report (it-ops-starter)
Done — wrote
it-ops-starter-semantic-spec.md.It mirrors the live module, so the entities, fields, relationships, enums, permissions, and roles come straight from what's deployed — trust those.
Three things to fix by hand (the live module doesn't store them, so I couldn't recover them):
- Overview is just a placeholder — the module's one-line tagline. Rewrite it into a couple of real sentences.
- Field descriptions are mostly blank; only a few fields carry one.
- Some record labels (e.g. "Contract Number") were guessed from the column name — skim them to make sure they read right.
Want the missing prose authored properly? Run
semantius-analystin Extend mode on this file.
Adapt the bullets to what actually applies to the module (drop any that don't; the Overview one almost always applies). Mention lost provenance metadata (license, source blueprint, related modules, the original request, personas) only if it matters to this reader, and in one line — never a key-by-key list.
Internal reference: faithful vs best-effort (use it to choose what to flag; never recite it)
Category A — faithful from live (trust; nothing to flag): all platform
frontmatter; §2 table & labels; the Mermaid edge set; every §3 entity annotation
(plural label, label column, audit log, edit permission, entity type, label parent,
reconciliation); every §3 field's name / format / required / Notes; §3 Relationships
prose; §4 rows; §5 enumerations; §8.1 permissions; §8.2 and §9 governance; §9.1
hierarchy. Entity order is the canonical entity_type tier then table_name A->Z, so
it round-trips against a convention-compliant spec.
Category B — best-effort or omitted (this is your fix-by-hand source):
- Authored frontmatter keys —
descriptionblock,blueprint_version,license,created_at,reconciled_*,source_blueprint,related_modules,related_domains,departments,initial_request,persona. Omitted (not persisted). - §1 Overview — seeded from the tagline.
- §2 Purpose column — first sentence of each entity description.
- §3 label-column titles — humanized field name (
contract_title→ "Contract Title"); irregulars likeapp_name→ "Application Name" are not recoverable. - §3 field Description — live truth, often empty.
- Built-in entity description (e.g.
users) — live value, not authored prose. - §6 / §7.1 / §7.2 — emitted
_(none)_. - A junction M:N's hand-authored business verb — the structure round-trips (canonical
"
X↔Yis many-to-many through the<junction>junction table"), the verb does not.
Drift check (only when comparing against an authored source spec). If a value the
platform does persist differs from the source spec, that is a forward-pipeline
(semantius-modeler / semantius-architect) bug, not a limitation here — surface it
separately and plainly. Observed on it-ops-starter: the modeler dropping the
label-field title and some field.description values; a malformed hyphen/underscore
role slug from the architect. A plain generate run has no source to diff, so this note
does not apply to it.
Stage 4: Audit the extracted spec for live-model defects (only when the user asks)
Why the analyst is the right auditor. semantius-analyst OWNS the spec artifact:
it authors specs (blueprint → spec) and its Mode B Audit is the canonical read-only
checker for a *-semantic-spec.md. Because this skill just wrote a spec, the analyst
audit is available — but on a reverse-engineered spec its value is specific: the
spec mirrors live state, so any real modeling defect the audit finds is a genuine
problem in the live module, now made visible. That is the point of running it.
Do not prompt for this. The skill ends at Stage 3. Never ask, offer, or pop up a
question about the audit (no AskUserQuestion, no trailing "want me to audit?" line).
Delivering the spec plus its Stage 3 verification is the end of a normal run. A
freshly generated spec does not need an unprompted audit, and the trailing question
reads as noise.
Run the audit ONLY when the user explicitly asks for it in a later turn (e.g. "audit
it", "check the live model for defects"). When they do, run the semantius-analyst
Mode B checks against the written file, and split the findings:
- Real live-model defects (surface as actionable): label-column-is-a-FK, missing
or filler
relationship_label, malformed JsonLogic, duplicatevalidation_rulescodes, an enum whose live values would orphan records. These describe the live module; fixing them means asemantius-modelerre-deploy. - Authoring-completeness findings (expected — do NOT surface as actionable):
missing
initial_request, empty §6/§7, missingdescriptionblock. These fire by construction on every extracted spec (they are the Category-B authored content live never held). Note them as expected, not as problems.
Do NOT confuse this authoring audit with an extraction-fidelity check. "Does the spec
faithfully match live?" is a different question, answered by re-running the extractor
(deterministic) or a semantius-modeler deploy-test round-trip — not by the analyst.
Verifying the extractor (for maintainers)
A reference module (it-ops-starter) and its hand-authored master spec
(semantius/specs/master-it-ops-starter-semantic-spec.md) anchor a round-trip
check: regenerate it-ops-starter-semantic-spec.md from live and confirm every
diff against the master falls in Category B. The master predates the canonical
entity-order convention, so its entity/section sequence differs from the extractor's
canonical order (compare Mermaid/§2/§3/§4/§5 order as sets, not line-by-line); a
value diff outside Category B is an extractor defect. Re-run this after any change to
spec-extract-lib.ts or a bump of the analyst template.
What this skill does not do
- Does not write to Semantius (read-only reverse-engineering).
- Does not capture user assignments, sample business data, or webhook logs.
- Does not invent authored content (§1 beyond a seed, §6/§7, authored frontmatter). Those are the analyst's job in Extend mode.