203 lines
7.5 KiB
Plaintext
203 lines
7.5 KiB
Plaintext
-- allium: 1
|
|
-- Workspace CLI tool (RuDS issue #19; distilled from bDS2 issue #25)
|
|
-- Scope: extension (Bucket G — MCP + Automation)
|
|
-- Distilled from: lib/bds/cli.ex, lib/bds/cli/commands.ex, lib/bds/cli/install.ex,
|
|
-- rel/overlays/cli/bin/bds-cli
|
|
|
|
entity CliInvocation {
|
|
command: rebuild | repair | render | upload | push | pull | post | media
|
|
| gallery | config | project | server | tui | lua | install
|
|
incremental: Boolean
|
|
force: Boolean
|
|
airplane: Boolean
|
|
json_output: Boolean
|
|
exit_code: Integer
|
|
-- Parsed by the native Clap binary: subcommands, options, flags, and auto-generated
|
|
-- help/version output. Unknown commands and invalid options exit 1
|
|
-- with formatted errors on stderr.
|
|
}
|
|
|
|
surface CliSurface {
|
|
facing _: CliRuntime
|
|
|
|
provides:
|
|
CliCommandExecuted(command)
|
|
CliInstallRequested()
|
|
}
|
|
|
|
invariant SharedDatabase {
|
|
-- The native CLI resolves the same OS application data path, settings,
|
|
-- project registry, and cache database as the GUI/TUI app — but with no
|
|
-- HTTP listener, no SSH daemon, no window, and no sync watcher.
|
|
-- Console logging is redirected to the rotating log file so stdout
|
|
-- carries only command output.
|
|
}
|
|
|
|
invariant CliWritesNotify {
|
|
-- Every CLI mutation (post/media/gallery creation, config set,
|
|
-- project add/switch, bulk rebuild/repair) inserts DbNotification
|
|
-- rows (from_cli: true) so a concurrently running app picks the
|
|
-- change up through its sync watcher (see cli_sync.allium). Bulk
|
|
-- maintenance uses wildcard entity ids per entity type.
|
|
}
|
|
|
|
rule ExitCode {
|
|
when: CliCommandExecuted(command)
|
|
-- Success prints the result (stdout) and exits 0; any error prints
|
|
-- to stderr and exits 1.
|
|
requires: CliInvocation.command = command
|
|
ensures: CliInvocation.exit_code.updated()
|
|
}
|
|
|
|
rule MachineOutput {
|
|
when: CliCommandExecuted(command)
|
|
requires: CliInvocation.json_output
|
|
-- Successful results use one stable JSON envelope on stdout; execution
|
|
-- errors use an error envelope on stderr and still exit 1.
|
|
ensures: CliInvocation.exit_code.updated()
|
|
}
|
|
|
|
rule AirplaneGate {
|
|
when: CliCommandExecuted(command)
|
|
requires: CliInvocation.airplane
|
|
-- --airplane blocks upload and Git network commands and routes all
|
|
-- automatic AI work exclusively to the configured local endpoint. If no
|
|
-- local endpoint exists, deterministic offline fallbacks or an explicit
|
|
-- notice are used; the online endpoint is never contacted.
|
|
ensures: OfflineAiGated()
|
|
}
|
|
|
|
rule RebuildFull {
|
|
when: CliCommandExecuted(command: rebuild)
|
|
requires: not CliInvocation.incremental
|
|
-- The same step sequence as the GUI "Rebuild Database"
|
|
-- (BDS.Maintenance.full_rebuild_steps — posts, media, scripts,
|
|
-- templates, post links, thumbnails, embedding index), run
|
|
-- synchronously with progress on stdout.
|
|
ensures: CacheDatabaseRebuilt()
|
|
}
|
|
|
|
rule RebuildIncremental {
|
|
when: CliCommandExecuted(command: rebuild)
|
|
requires: CliInvocation.incremental
|
|
-- Metadata diff, then auto-apply file→db for every difference and
|
|
-- import every orphan file.
|
|
ensures: CacheDatabaseRebuilt()
|
|
}
|
|
|
|
rule Repair {
|
|
when: CliCommandExecuted(command: repair)
|
|
-- Subcommand argument selects the repair part: post-links,
|
|
-- media-links, thumbnails, embeddings, or search — the standard
|
|
-- rebuild tasks outside the full rebuild.
|
|
ensures: RepairTaskCompleted()
|
|
}
|
|
|
|
rule Render {
|
|
when: CliCommandExecuted(command: render)
|
|
-- Default: render all site sections plus the search index.
|
|
-- --incremental: validate the generated output and apply only the
|
|
-- differences (targeted render + extra-file deletion + calendar).
|
|
-- --force: full re-render ignoring (but updating) content hashes.
|
|
requires: not (CliInvocation.incremental and CliInvocation.force)
|
|
ensures: SiteRendered()
|
|
}
|
|
|
|
rule Upload {
|
|
when: CliCommandExecuted(command: upload)
|
|
-- Uses the project publishing preferences (ssh host/user/path/mode)
|
|
-- exactly like the app's upload, and waits for the publish job.
|
|
ensures: SiteUploaded()
|
|
}
|
|
|
|
rule GitSync {
|
|
when: CliCommandExecuted(command: push | pull)
|
|
-- push: git push of the project repository to origin.
|
|
-- pull: git pull --ff-only, then the incremental cache update
|
|
-- (metadata diff auto-apply + orphan import) so the database
|
|
-- reflects the pulled files.
|
|
ensures: RepositorySynchronized()
|
|
}
|
|
|
|
rule CreatePost {
|
|
when: CliCommandExecuted(command: post)
|
|
-- Post data from parameters or JSON on stdin (LLM-friendly).
|
|
-- Language is auto-detected when missing: the configured AI
|
|
-- endpoint (airplane mode routes to the local model), falling back
|
|
-- to the offline heuristic with a printed notice — the CLI
|
|
-- equivalent of the airplane-mode toast. After creation the same
|
|
-- auto-translation as the GUI is scheduled and awaited; when
|
|
-- nothing can be scheduled the user is told.
|
|
ensures: PostCreated()
|
|
}
|
|
|
|
rule CreateMedia {
|
|
when: CliCommandExecuted(command: media)
|
|
-- Imports the image, then best-effort AI enrichment: generated
|
|
-- title, alt text, caption, and translations to all configured
|
|
-- blog languages (the gallery pipeline without post linking).
|
|
ensures: MediaImported()
|
|
}
|
|
|
|
rule CreateGallery {
|
|
when: CliCommandExecuted(command: gallery)
|
|
-- Creates the post, then runs the shared gallery import pipeline
|
|
-- for every referenced image: import, mandatory post link, AI
|
|
-- enrichment, translations; finally the post auto-translation.
|
|
ensures: PostCreated()
|
|
ensures: MediaImported()
|
|
}
|
|
|
|
rule Preferences {
|
|
when: CliCommandExecuted(command: config)
|
|
-- get/set/list of the global settings store shared with the app.
|
|
ensures: PreferencesAccessed()
|
|
}
|
|
|
|
rule Projects {
|
|
when: CliCommandExecuted(command: project)
|
|
-- list, add <path> (register a folder in the cache database), and
|
|
-- switch <id|slug|name> (change the active project).
|
|
ensures: ProjectRegistryUpdated()
|
|
}
|
|
|
|
rule Tui {
|
|
when: CliCommandExecuted(command: tui)
|
|
-- The native CLI enters TUI boot mode so the interactive terminal UI owns
|
|
-- the terminal.
|
|
ensures: TuiStarted()
|
|
}
|
|
|
|
rule Server {
|
|
when: CliCommandExecuted(command: server)
|
|
-- Starts the dedicated headless SSH host with optional bind address, port,
|
|
-- database path, and data-directory overrides. The standalone bds-server
|
|
-- executable is not distributed.
|
|
ensures: SshDaemonStarted()
|
|
}
|
|
|
|
rule RunLuaTask {
|
|
when: CliCommandExecuted(command: lua)
|
|
-- Runs a utility ("task", long-running) script from the database by
|
|
-- slug in the active project, with the managed-job execution budget
|
|
-- (unlimited time/reductions) but synchronously. Macro and
|
|
-- transform scripts are rejected.
|
|
ensures: ScriptExecuted()
|
|
}
|
|
|
|
rule InstallLauncher {
|
|
when: CliInstallRequested() or CliCommandExecuted(command: install)
|
|
-- Settings/Data, the future TUI settings action, and `bds-cli install`
|
|
-- share one guarded installer. A forwarding launcher written to
|
|
-- ~/.local/bin/bds-cli executes the packaged native CLI in place, so it
|
|
-- uses the same packaged runtime as the desktop app. Existing unrelated
|
|
-- files are never overwritten; outside a packaged release the action
|
|
-- reports that the packaged CLI executable is required.
|
|
ensures: LauncherInstalled()
|
|
}
|
|
|
|
invariant NativeArgv {
|
|
-- The forwarding launcher preserves operating-system argv for the native
|
|
-- bds-cli executable without the bDS2 release-eval environment shim.
|
|
}
|