Formalize tier-1 comment-based specs into allium constructs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bauer, Georg
2026-07-22 14:58:22 +02:00
parent 1dd8194fa8
commit 733aa9a6ff
9 changed files with 1088 additions and 471 deletions

View File

@@ -40,6 +40,7 @@ surface TemplateEditorSurface {
when editor.can_publish
TemplateValidateRequested(editor.template_id)
TemplateDeleteRequested(editor.template_id)
TemplateForceDeleteConfirmed(editor.template_id)
@guarantee HeaderLayout
-- Header bar with template title tab.
@@ -65,36 +66,75 @@ surface TemplateEditorSurface {
rule TemplateSave {
when: TemplateSaveRequested(template_id)
-- Liquid validation first (parse check for syntax errors)
-- If invalid: blocks save, shows error inline in editor
-- If valid: bumps version, saves to DB + rewrites .liquid file
-- See engine_side_effects.allium UpdateTemplateSideEffects
let target = template/Template{id: template_id}
let validation = ValidateLiquid(editor_content(template_id))
-- editor_content: the current code editor buffer
ensures:
if validation = valid:
UpdateTemplateRequested(target, editor_field_changes(template_id))
-- Version bump + DB write + .liquid rewrite:
-- template.allium UpdateTemplate,
-- engine_side_effects.allium UpdateTemplateSideEffects
else:
TemplateValidationErrorsShown(template_id, validation)
-- Save blocked; errors shown inline in the editor
}
rule TemplatePublish {
when: TemplatePublishRequested(template_id)
-- Only offered while the template is a draft (can_publish gate on the button)
-- Validates Liquid first (publish gate); invalid source blocks publish
-- Saves current draft fields, then publishes (status -> published)
-- Writes the published .liquid file to disk
-- See template.allium PublishTemplate
let target = template/Template{id: template_id}
requires: target.status = draft
-- can_publish gate on the button
let validation = ValidateLiquid(editor_content(template_id))
ensures:
if validation = valid:
UpdateTemplateRequested(target, editor_field_changes(template_id))
PublishTemplateRequested(target)
-- status -> published + .liquid file write:
-- template.allium PublishTemplate
else:
TemplateValidationErrorsShown(template_id, validation)
}
rule TemplateValidate {
when: TemplateValidateRequested(template_id)
-- Validates Liquid syntax without saving
-- Shows errors inline in editor
-- Success shown as toast or status indicator
-- Validation only, never saves
let validation = ValidateLiquid(editor_content(template_id))
ensures:
if validation = valid:
TemplateValidationOkShown(template_id)
-- toast / status indicator
else:
TemplateValidationErrorsShown(template_id, validation)
}
rule TemplateDelete {
when: TemplateDeleteRequested(template_id)
-- Checks for references: posts using this template, tags with postTemplateSlug
-- If references exist: system confirm dialog
-- "This template is used by N posts and M tags. Force delete?"
-- Force delete: nulls templateSlug on referencing posts,
-- nulls postTemplateSlug on referencing tags
-- If no references: deletes without confirmation
-- Deletes DB record + .liquid file on disk
-- Closes template tab, sidebar removes item
let target = template/Template{id: template_id}
let references = target.referencing_posts.count + target.referencing_tags.count
ensures:
if references > 0:
TemplateForceDeleteConfirmShown(template_id)
-- system confirm dialog: "This template is used by N posts
-- and M tags. Force delete?" (action_patterns.allium
-- confirmation_assignments: template_delete_with_references)
else:
DeleteTemplateRequested(target)
closeTab(template_id)
-- no confirmation when nothing references the template
}
rule TemplateForceDelete {
when: TemplateForceDeleteConfirmed(template_id)
let target = template/Template{id: template_id}
-- Clear references first so template.allium DeleteTemplate's
-- zero-reference precondition holds:
for p in target.referencing_posts:
ensures: p.template_slug = null
for t in target.referencing_tags:
ensures: t.post_template_slug = null
ensures: DeleteTemplateRequested(target)
-- DB record + .liquid file on disk
ensures: closeTab(template_id)
-- sidebar removes the item reactively
}