|
|
|
|
@@ -8,6 +8,10 @@
|
|
|
|
|
|
|
|
|
|
config {
|
|
|
|
|
script_extension: String = "lua"
|
|
|
|
|
macro_timeout: Duration = 10.seconds
|
|
|
|
|
transform_max_toasts_per_script: Integer = 5
|
|
|
|
|
transform_max_toasts_total: Integer = 20
|
|
|
|
|
transform_max_toast_length: Integer = 300
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ScriptStatus {
|
|
|
|
|
@@ -70,6 +74,44 @@ surface ScriptManagementSurface {
|
|
|
|
|
RebuildScriptsFromFilesRequested(project)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
surface ScriptRuntimeSurface {
|
|
|
|
|
facing _: ScriptRuntime
|
|
|
|
|
|
|
|
|
|
provides:
|
|
|
|
|
ValidateScript(source)
|
|
|
|
|
ExecuteScriptRequested(script, entrypoint, args, progress_sink)
|
|
|
|
|
|
|
|
|
|
@guarantee SandboxedExecution
|
|
|
|
|
-- User-authored Lua executes from a sandboxed runtime state.
|
|
|
|
|
-- Filesystem mutation, process control, package loading, and other
|
|
|
|
|
-- unrestricted host capabilities are unavailable unless explicitly
|
|
|
|
|
-- re-exposed by the host application.
|
|
|
|
|
|
|
|
|
|
@guarantee ExplicitHostCapabilities
|
|
|
|
|
-- Host-provided functions are exposed only through an explicit bds.*
|
|
|
|
|
-- capability table, never through ambient global access.
|
|
|
|
|
|
|
|
|
|
@guarantee MacroTimeout
|
|
|
|
|
-- Macro execution has a short timeout budget of config.macro_timeout.
|
|
|
|
|
|
|
|
|
|
@guarantee ManagedBatchExecution
|
|
|
|
|
-- Utility and transform scripts execute as managed jobs.
|
|
|
|
|
-- The contract does not define a fixed wall-clock limit for those
|
|
|
|
|
-- jobs because batch work can legitimately scale with project size.
|
|
|
|
|
-- Progress reporting, operator cancellation, and host orchestration
|
|
|
|
|
-- govern their lifecycle instead of a fixed timeout.
|
|
|
|
|
|
|
|
|
|
@guarantee ProgressFeedback
|
|
|
|
|
-- Long-running utility and transform scripts may emit progress updates
|
|
|
|
|
-- through explicit host APIs during execution.
|
|
|
|
|
-- Progress reporting is cooperative and flows through the supplied
|
|
|
|
|
-- progress sink rather than ambient global side effects.
|
|
|
|
|
|
|
|
|
|
@guarantee BatchCancellation
|
|
|
|
|
-- Managed utility and transform jobs can be cancelled by the host
|
|
|
|
|
-- operator boundary.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
invariant UniqueScriptSlug {
|
|
|
|
|
for a in Scripts:
|
|
|
|
|
for b in Scripts:
|
|
|
|
|
@@ -92,7 +134,7 @@ rule CreateScript {
|
|
|
|
|
title: title,
|
|
|
|
|
kind: kind,
|
|
|
|
|
content: content,
|
|
|
|
|
entrypoint: entrypoint ?? "render",
|
|
|
|
|
entrypoint: entrypoint ?? if kind = macro: "render" else: "main",
|
|
|
|
|
status: draft,
|
|
|
|
|
enabled: true,
|
|
|
|
|
version: 1,
|
|
|
|
|
@@ -127,7 +169,7 @@ rule CreateAndPublishScript {
|
|
|
|
|
title: title,
|
|
|
|
|
kind: kind,
|
|
|
|
|
content: null,
|
|
|
|
|
entrypoint: entrypoint ?? "render",
|
|
|
|
|
entrypoint: entrypoint ?? if kind = macro: "render" else: "main",
|
|
|
|
|
status: published,
|
|
|
|
|
enabled: true,
|
|
|
|
|
version: 1,
|
|
|
|
|
@@ -158,11 +200,17 @@ rule ExecuteMacro {
|
|
|
|
|
when: MacroExpansionRequested(script, template_context)
|
|
|
|
|
requires: script.kind = macro
|
|
|
|
|
requires: script.enabled = true
|
|
|
|
|
requires: script.entrypoint != ""
|
|
|
|
|
-- Macro scripts are invoked during template rendering
|
|
|
|
|
-- via [[slug param1=value1 param2=value2]] syntax in post content
|
|
|
|
|
-- They receive named parameters and the template context, return HTML
|
|
|
|
|
-- from a bounded Lua execution environment that exposes only approved
|
|
|
|
|
-- host capabilities
|
|
|
|
|
-- Unknown macro names are resolved against enabled macro scripts by slug.
|
|
|
|
|
-- They receive named parameters plus template_context.env fields that
|
|
|
|
|
-- include isPreview, mainLanguage, languagePrefix, hook, source.kind,
|
|
|
|
|
-- and translations.
|
|
|
|
|
-- They return HTML and run sequentially with config.macro_timeout per
|
|
|
|
|
-- invocation.
|
|
|
|
|
-- Macro failures degrade to empty output for that invocation and do not
|
|
|
|
|
-- abort rendering of the surrounding page.
|
|
|
|
|
ensures: MacroOutputProduced(script, html_output)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -170,8 +218,11 @@ rule ExecuteUtility {
|
|
|
|
|
when: RunUtilityRequested(script)
|
|
|
|
|
requires: script.kind = utility
|
|
|
|
|
requires: script.enabled = true
|
|
|
|
|
-- Runs on-demand from the UI in a bounded Lua execution environment,
|
|
|
|
|
-- produces stdout output
|
|
|
|
|
requires: script.entrypoint != ""
|
|
|
|
|
-- Utility scripts commonly perform long-running data manipulation work.
|
|
|
|
|
-- They are manually started by an operator action, run as managed jobs,
|
|
|
|
|
-- may issue host-backed API calls, may emit progress during execution,
|
|
|
|
|
-- and may be cancelled by the operator.
|
|
|
|
|
ensures: UtilityOutputProduced(script, stdout)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -180,14 +231,35 @@ rule ExecuteTransform {
|
|
|
|
|
-- Transform scripts run sequentially on blogmark deep link data
|
|
|
|
|
-- Input: title, content, tags, categories, source url
|
|
|
|
|
-- Each transform can modify the data before post creation.
|
|
|
|
|
-- Execution uses the same bounded Lua host API contract as other scripts.
|
|
|
|
|
-- Execution uses the same managed job host API contract as other batch
|
|
|
|
|
-- scripts and may report progress while mass-processing remote or local
|
|
|
|
|
-- content.
|
|
|
|
|
let transforms = Scripts where kind = transform and enabled = true
|
|
|
|
|
for t in ordered_by(transforms, s => s.slug):
|
|
|
|
|
for t in ordered_by(transforms, s => s.updated_at, s => s.slug, s => s.id):
|
|
|
|
|
requires: t.entrypoint != ""
|
|
|
|
|
ensures: TransformApplied(t, data)
|
|
|
|
|
|
|
|
|
|
@guarantee TransformTrigger
|
|
|
|
|
-- Transform scripts are triggered automatically by blogmark import.
|
|
|
|
|
-- Each script receives the current post candidate plus a context with
|
|
|
|
|
-- source='blogmark' and the originating URL.
|
|
|
|
|
|
|
|
|
|
@guarantee TransformPipelineContinuation
|
|
|
|
|
-- Transform errors are captured per script and do not roll back the
|
|
|
|
|
-- last valid post state produced by earlier transforms.
|
|
|
|
|
-- The pipeline continues with subsequent enabled transforms.
|
|
|
|
|
|
|
|
|
|
@guarantee TransformToastBudget
|
|
|
|
|
-- Transform scripts may emit toast feedback.
|
|
|
|
|
-- At most config.transform_max_toasts_per_script toasts are accepted
|
|
|
|
|
-- from any one transform, with a total budget of
|
|
|
|
|
-- config.transform_max_toasts_total across the pipeline.
|
|
|
|
|
-- Individual toast messages are truncated to
|
|
|
|
|
-- config.transform_max_toast_length characters.
|
|
|
|
|
|
|
|
|
|
@guidance
|
|
|
|
|
-- bds://new-post deep links from browser bookmarks
|
|
|
|
|
-- Max 5 toast notifications per script, 20 total
|
|
|
|
|
-- Ordering is deterministic: updated_at, then slug, then id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rule RebuildScriptsFromFiles {
|
|
|
|
|
|