@gregiteen/ssss-cli 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/LICENSE +15 -0
  3. package/README.md +162 -0
  4. package/VERSION +1 -0
  5. package/conformance/README.md +72 -0
  6. package/conformance/fixtures.json +763 -0
  7. package/conformance/reference-bundle.ucw.json +135 -0
  8. package/docs/help/autolink.md +15 -0
  9. package/docs/help/bundle.md +47 -0
  10. package/docs/help/conformance.md +34 -0
  11. package/docs/help/export.md +20 -0
  12. package/docs/help/import.md +19 -0
  13. package/docs/help/overview.md +33 -0
  14. package/docs/help/portability.md +27 -0
  15. package/docs/help/provision.md +19 -0
  16. package/docs/help/provisioning.md +43 -0
  17. package/docs/help/roles.md +61 -0
  18. package/docs/help/runtime.md +78 -0
  19. package/docs/help/scaffold.md +47 -0
  20. package/docs/ssss-spec.md +1325 -0
  21. package/package.json +62 -0
  22. package/registry/core.json +225 -0
  23. package/registry/extensions/festech.json +134 -0
  24. package/scripts/audit-registry-field-usage.mjs +136 -0
  25. package/scripts/autolink.mjs +341 -0
  26. package/scripts/build-reference-bundle.mjs +169 -0
  27. package/scripts/cmd-export.mjs +72 -0
  28. package/scripts/cmd-help.mjs +60 -0
  29. package/scripts/cmd-import.mjs +71 -0
  30. package/scripts/cmd-inspect.mjs +78 -0
  31. package/scripts/cmd-new.mjs +262 -0
  32. package/scripts/cmd-provision.mjs +68 -0
  33. package/scripts/cmd-validate.mjs +43 -0
  34. package/scripts/conformance.mjs +408 -0
  35. package/scripts/lib/cli.mjs +92 -0
  36. package/scripts/release.sh +35 -0
  37. package/scripts/ssss.mjs +93 -0
  38. package/scripts/validate-skills.mjs +115 -0
  39. package/src/bundle.mjs +261 -0
  40. package/src/engine.mjs +452 -0
  41. package/src/frontmatter.mjs +109 -0
  42. package/src/registry.mjs +67 -0
  43. package/src/runtime.mjs +212 -0
@@ -0,0 +1,135 @@
1
+ {
2
+ "manifest": {
3
+ "name": "Festival in a Box",
4
+ "description": "A complete music-festival operation as a tradeable SSSS bundle.",
5
+ "version": "1.0.0",
6
+ "exported_at": "1970-01-01T00:00:00.000Z",
7
+ "ssss_core_version": "0.6",
8
+ "required_extensions": [
9
+ "festech"
10
+ ],
11
+ "export_profile": "sale",
12
+ "primitive_inventory": {
13
+ "assistant": 1,
14
+ "domain": 1,
15
+ "page": 1,
16
+ "security_role": 1,
17
+ "rule": 1,
18
+ "workflow": 1
19
+ },
20
+ "provisioning": [
21
+ {
22
+ "id": "ws",
23
+ "label": "Create the workspace",
24
+ "system": "workspace",
25
+ "mode": "generate",
26
+ "required": true
27
+ },
28
+ {
29
+ "id": "dom",
30
+ "label": "Bind the festival domain",
31
+ "system": "domains",
32
+ "mode": "provision",
33
+ "required": true,
34
+ "notes": "owns_domain — buyer supplies their own domain."
35
+ },
36
+ {
37
+ "id": "mail",
38
+ "label": "Provision a support mailbox",
39
+ "system": "email",
40
+ "mode": "provision",
41
+ "required": false
42
+ }
43
+ ],
44
+ "parameters": [
45
+ {
46
+ "key": "business_name",
47
+ "label": "Festival name",
48
+ "type": "string",
49
+ "scope": "workspace",
50
+ "source": "user",
51
+ "required": true
52
+ },
53
+ {
54
+ "key": "domain",
55
+ "label": "Domain to bind",
56
+ "type": "string",
57
+ "scope": "workspace",
58
+ "source": "user",
59
+ "required": true,
60
+ "description": "Satisfies the resource_bound domain requirement (owns_domain)."
61
+ },
62
+ {
63
+ "key": "support_mailbox",
64
+ "label": "Support mailbox",
65
+ "type": "string",
66
+ "scope": "workspace",
67
+ "source": "user",
68
+ "required": false
69
+ }
70
+ ],
71
+ "file_count": 14,
72
+ "provenance": {
73
+ "content_hash": "sha256:96380f618ee1e178331beca9507e1b3cd28a3d12cfa7f9898317f98da8295218",
74
+ "exporter": "@ssss/cli@0.7.0"
75
+ }
76
+ },
77
+ "files": [
78
+ {
79
+ "path": "assistants/concierge.md",
80
+ "content": "---\ntype: assistant\ntitle: Festival Concierge\ndescription: Assistant that answers attendee questions about the lineup and venue.\ntimestamp: 2026-07-02T00:00:00Z\nname: Festival Concierge\nslug: concierge\n---\nAnswer attendee questions about the lineup and venue."
81
+ },
82
+ {
83
+ "path": "assistants/index.md",
84
+ "content": "# Index — assistants\n\n- [Festival Concierge](./concierge.md)\n"
85
+ },
86
+ {
87
+ "path": "domains/festival.md",
88
+ "content": "---\ntype: domain\ntitle: Festival Domain Requirement\ndescription: Domain resource requirement that the buyer binds during provisioning.\ntimestamp: 2026-07-02T00:00:00Z\ndomain_name: REQUIREMENT\nregistrar: REQUIREMENT\nstatus: required\npayment_status: unbound\nx_portability: resource_bound\n---\nThis festival needs a domain. The buyer binds their own at provision (owns_domain)."
89
+ },
90
+ {
91
+ "path": "domains/index.md",
92
+ "content": "# Index — domains\n\n- [Festival Domain Requirement](./festival.md)\n"
93
+ },
94
+ {
95
+ "path": "pages/index.md",
96
+ "content": "# Index — pages\n\n- [Lineup](./lineup.md)\n"
97
+ },
98
+ {
99
+ "path": "pages/lineup.md",
100
+ "content": "---\ntype: page\ntitle: Lineup\ndescription: Public-facing festival lineup page.\ntimestamp: 2026-07-02T00:00:00Z\nslug: lineup\nname: Lineup\nsandbox_entry: lineup/index.html\n---\nThe festival lineup page."
101
+ },
102
+ {
103
+ "path": "roles/admin/ROLE.md",
104
+ "content": "---\ntype: security_role\ntitle: Administrator Role\ndescription: Security role with full festival operations write access.\ntimestamp: 2026-07-02T00:00:00Z\nname: Administrator\npermissions:\n - \"write:assistant\"\n - \"write:workflow\"\n - \"write:rule\"\n - \"write:domain\"\n - \"write:page\"\n - \"write:security_role\"\n - \"write:task\"\n---\nFull access to all festival operations."
105
+ },
106
+ {
107
+ "path": "roles/admin/index.md",
108
+ "content": "# Index — roles/admin\n\n- [Administrator Role](./ROLE.md)\n"
109
+ },
110
+ {
111
+ "path": "roles/index.md",
112
+ "content": "# Index — roles\n\n- [admin/](./admin/index.md)\n"
113
+ },
114
+ {
115
+ "path": "rules/index.md",
116
+ "content": "# Index — rules\n\n- [Refund Policy](./refund-policy.md)\n"
117
+ },
118
+ {
119
+ "path": "rules/refund-policy.md",
120
+ "content": "---\ntype: rule\ntitle: Refund Policy\ndescription: Refund eligibility rule for festival attendees.\ntimestamp: 2026-07-02T00:00:00Z\nname: Refund Policy\nslug: refund-policy\n---\nRefunds are available up to 14 days before the event."
121
+ },
122
+ {
123
+ "path": "tasks/index.md",
124
+ "content": "# Index — tasks\n\n- [Ticket 4821 Seat Change](./ticket-4821.md)\n"
125
+ },
126
+ {
127
+ "path": "workflows/box-office.md",
128
+ "content": "---\ntype: workflow\ntitle: Box Office\ndescription: Ticket-sales workflow for a music festival.\ntimestamp: 2026-07-02T00:00:00Z\nname: Box Office\nslug: box-office\n---\nSell tickets, then hand the buyer to [[concierge]] for questions."
129
+ },
130
+ {
131
+ "path": "workflows/index.md",
132
+ "content": "# Index — workflows\n\n- [Box Office](./box-office.md)\n"
133
+ }
134
+ ]
135
+ }
@@ -0,0 +1,15 @@
1
+ # `ssss autolink`
2
+
3
+ Generate OKF wiki-links across an SSSS vault. Rewrites bare references to
4
+ `[[slug]]` links so a vault is navigable as an "LLM-wiki," using bundle-relative
5
+ absolute paths. Deterministic and idempotent — running it twice changes nothing.
6
+
7
+ ```bash
8
+ ssss autolink [dir] # default dir: the current directory
9
+ ```
10
+
11
+ The same rewrite engine backs provisioning's id-remap (§17.3): when `provision`
12
+ relocates files under a `--prefix`, link targets are recomputed the same way, so
13
+ internal links never dangle after a move.
14
+
15
+ See also: `ssss help provisioning`.
@@ -0,0 +1,47 @@
1
+ # The `.ucw` bundle format (spec §16)
2
+
3
+ A `.ucw` bundle is the transportable package of a vault — "a festival in a box."
4
+ It is plain JSON: a manifest plus the path-sorted vault files, content-hashed for
5
+ integrity. The container file is conventionally named `*.ucw.json`.
6
+
7
+ ## Shape
8
+
9
+ ```jsonc
10
+ {
11
+ "manifest": {
12
+ "name": "Festival in a Box",
13
+ "description": "...",
14
+ "version": "0.1.0",
15
+ "exported_at": "1970-01-01T00:00:00.000Z", // frozen → deterministic export
16
+ "ssss_core_version": "0.6",
17
+ "required_extensions": ["festech"],
18
+ "export_profile": "sale", // backup | template | sale
19
+ "primitive_inventory": { "workflow": 1, "page": 1, "rule": 1, "assistant": 1, "domain": 1 },
20
+ "provisioning": [ /* steps, see `ssss help provisioning` */ ],
21
+ "parameters": [ /* template variables, see below */ ],
22
+ "file_count": 5,
23
+ "provenance": {
24
+ "content_hash": "sha256:…", // over the canonical file serialization
25
+ "exporter": "@ssss/cli"
26
+ }
27
+ },
28
+ "files": [ { "path": "rules/refund-policy.md", "content": "---\n…" } ]
29
+ }
30
+ ```
31
+
32
+ ## Integrity
33
+
34
+ `provenance.content_hash` is `sha256` over the canonical (path-sorted) serialization
35
+ of `files`. `ssss validate` recomputes it and rejects any mismatch — a bundle cannot
36
+ be silently edited. `primitive_inventory` is registry-driven (a count per `type`),
37
+ not a closed category enum.
38
+
39
+ ## Parameters
40
+
41
+ Each entry in `parameters[]` is a template variable resolved at provision time:
42
+ `{ key, label, type, scope, source }` where `source ∈ user | llm | graph | system`.
43
+ Required parameters must be supplied (`ssss provision --param key=value`) or the
44
+ plan is rejected.
45
+
46
+ Commands: `ssss export`, `ssss validate`, `ssss inspect`.
47
+ See also: `ssss help provisioning`, `ssss help portability`.
@@ -0,0 +1,34 @@
1
+ # Conformance (spec §12)
2
+
3
+ A host MUST NOT claim SSSS conformance without passing the canonical suite in
4
+ `conformance/`. It is the shared test every implementation runs.
5
+
6
+ ```bash
7
+ ssss conformance # structural + registry portability validation
8
+ ssss conformance --engine # also replay every fixture + round-trip the reference bundle in-process
9
+ ssss conformance --endpoint <url> --token <pat> # run the fixtures against a live host
10
+ ```
11
+
12
+ ## What `--engine` proves
13
+
14
+ 1. **All Operation Contract fixtures** (`conformance/fixtures.json`) replay through
15
+ the reference engine (`src/engine.mjs`) and produce the expected responses —
16
+ create/patch/event/delete, dry-run, idempotency, and failure cases.
17
+ 2. **The reference bundle round-trips**: `validate → provision → import → re-import`
18
+ on `conformance/reference-bundle.ucw.json`, asserting
19
+ - the bundle's schema + content hash are valid,
20
+ - the `sale` profile carries no `tenant_private` file,
21
+ - provision resolves parameters and link integrity,
22
+ - import commits every file, and a second import commits **zero** (idempotent),
23
+ - no `tenant_private` file ever lands on disk.
24
+ 3. **Workflow runtime checks** (`src/runtime.mjs`) prove a workflow trigger plans
25
+ deterministic event/task envelopes, duplicate daemon ticks replay idempotently,
26
+ and worker-created runs commit through the Operation Contract.
27
+
28
+ ## Endpoint mode
29
+
30
+ `--endpoint` POSTs each fixture's `request` to a host's Operation Contract endpoint
31
+ and diffs the response — this is how festech / ultrachat / total-recall prove they
32
+ implement the *same* standard rather than three drifting copies.
33
+
34
+ See also: `conformance/README.md`, `ssss help runtime`, `ssss help provisioning`.
@@ -0,0 +1,20 @@
1
+ # `ssss export`
2
+
3
+ Package a vault directory into a `.ucw` bundle (spec §16). Pure and deterministic:
4
+ the same vault + profile yields a byte-identical bundle (the timestamp is frozen and
5
+ the files are content-hashed), so exports are diffable and cacheable.
6
+
7
+ ```bash
8
+ ssss export <vault-dir> [--profile backup|template|sale] [--out file.ucw.json]
9
+ ```
10
+
11
+ Walks every `*.md` under the vault (skipping dotfiles and the `.events` log), reads
12
+ each file's `type` from frontmatter, resolves its portability class (§5.5), and keeps
13
+ only the classes the profile permits. The dropped files are reported with
14
+ `--show-dropped`.
15
+
16
+ Common flags: `--name`, `--description`, `--bundle-version`, `--exporter`,
17
+ `--ext <name>` (declare a required extension, repeatable), `--registry <dir>`.
18
+
19
+ Run `ssss export --help` for the full flag list.
20
+ See also: `ssss help portability`, `ssss help bundle`.
@@ -0,0 +1,19 @@
1
+ # `ssss import`
2
+
3
+ Replay a bundle (or a pre-built plan) into a target vault through the reference
4
+ engine (spec §17.1, §6). Idempotent: each envelope carries a deterministic
5
+ idempotency key, so importing the same bundle twice commits nothing the second time.
6
+
7
+ ```bash
8
+ ssss import <bundle.ucw.json> --vault <dir> [--param key=value]
9
+ ssss import --plan plan.json --vault <dir> # replay a plan from `ssss provision`
10
+ ```
11
+
12
+ - `--vault <dir>` is required and is created if missing.
13
+ - Without `--plan`, import provisions inline first (resolving `--param` flags); a
14
+ failed provision (unresolved params / dangling links) aborts before any write.
15
+ - `--dry-run` validates every envelope without committing.
16
+ - The summary reports `committed`, `unchanged (idempotent)`, and `failed` counts.
17
+
18
+ Run `ssss import --help` for the full flag list.
19
+ See also: `ssss help provisioning`, `ssss provision`.
@@ -0,0 +1,33 @@
1
+ # SSSS — overview
2
+
3
+ The **Structured Semantic Syntax System** is a database-free, Markdown-first schema
4
+ and mutation contract for AI-agent state. A vault is a directory of Markdown files
5
+ with YAML frontmatter; every file declares a `type` defined in the registry.
6
+
7
+ `@ssss/cli` is the reference implementation: a dependency-free Operation Contract
8
+ engine, a registry-driven validator, and the `.ucw` bundle/provisioning tooling.
9
+
10
+ ## The pieces
11
+
12
+ | Piece | Where | What it is |
13
+ |-------|-------|------------|
14
+ | Spec | `docs/ssss-spec.md` | The normative standard. |
15
+ | Core registry | `registry/core.json` | The 14 document primitives + 5 contract primitives, plus the bundle (§16) and provisioning (§17) schemas. |
16
+ | Engine | `src/engine.mjs` | The §6 Operation Contract pipeline (operation/patch/event/delete). |
17
+ | Runtime | `src/runtime.mjs` | The §11.8 workflow trigger → event/task/run envelope planner. |
18
+ | Bundle | `src/bundle.mjs` | export / validate / provision / import (§16–§17). |
19
+ | Conformance | `conformance/` | Fixtures every host must pass. |
20
+
21
+ ## The lifecycle
22
+
23
+ ```
24
+ vault ──export──▶ .ucw bundle ──provision──▶ envelope plan ──import──▶ new vault
25
+ (§16, pure) (§17, params + links) (§6, idempotent)
26
+ ```
27
+
28
+ ## Commands
29
+
30
+ Run `ssss help <topic>` for any of:
31
+ `runtime`, `portability`, `bundle`, `provisioning`, `export`, `provision`, `import`, `conformance`, `autolink`.
32
+
33
+ Run `ssss <command> --help` for: `export`, `validate`, `inspect`, `provision`, `import`, `autolink`, `conformance`.
@@ -0,0 +1,27 @@
1
+ # Portability classification (spec §5.5) — the keystone
2
+
3
+ Every document primitive declares a **portability class**. This is what makes a
4
+ vault sellable without leaking the operator's private data.
5
+
6
+ | Class | Meaning | Example types |
7
+ |-------|---------|---------------|
8
+ | `structural` | The sellable business model — the thing a buyer wants. | `workflow`, `rule`, `page`, `assistant` |
9
+ | `tenant_private` | The operator's private data. **Never** sold or templated. | `task`, customer records |
10
+ | `resource_bound` | Needs a real resource bound at provision time. | `domain`, `phone_number`, `integration_connection` |
11
+
12
+ A file MAY override its type default with `x_portability` in frontmatter. The most
13
+ restrictive of (type default, override) wins.
14
+
15
+ ## Export profiles are filters over the classes
16
+
17
+ | Profile | Includes | Use |
18
+ |---------|----------|-----|
19
+ | `backup` | structural + tenant_private + resource_bound | Full operator backup/restore. |
20
+ | `template` | structural + resource_bound | A reusable template, private data stripped. |
21
+ | `sale` | structural + resource_bound | A tradeable business, private data stripped. |
22
+
23
+ > `template` and `sale` exports MUST drop every `tenant_private` primitive. The
24
+ > reference bundle (`conformance/reference-bundle.ucw.json`) proves this: its
25
+ > `task` ticket is dropped from the `sale` export.
26
+
27
+ See also: `ssss help bundle`, `ssss help export`.
@@ -0,0 +1,19 @@
1
+ # `ssss provision`
2
+
3
+ Plan a bundle install (spec §17): resolve parameters, check link integrity under
4
+ id-remap, and emit an ordered list of Operation Contract envelopes. Pure — it never
5
+ touches the filesystem, so it is safe to run and diff before importing.
6
+
7
+ ```bash
8
+ ssss provision <bundle.ucw.json> --param key=value [--workspace id] [--prefix path] [--out plan.json]
9
+ ```
10
+
11
+ - Required parameters that are neither supplied nor defaulted cause a non-zero exit.
12
+ - Any `[[link]]` that points outside the bundle is reported as a dangling link and
13
+ fails the plan.
14
+ - `--prefix` relocates every file under a target path; link checks follow the remap.
15
+ - Each envelope gets a deterministic idempotency key, so the resulting plan is safe
16
+ to import more than once.
17
+
18
+ Run `ssss provision --help` for the full flag list.
19
+ See also: `ssss help provisioning`, `ssss import`.
@@ -0,0 +1,43 @@
1
+ # The provisioning contract (spec §17)
2
+
3
+ Three deterministic, idempotent verbs move a bundle from an export into a live vault.
4
+
5
+ | Verb | Signature | What it does |
6
+ |------|-----------|--------------|
7
+ | `export` | vault + profile → bundle | Pure. Profile-filtered, content-hashed. |
8
+ | `provision` | bundle + params → plan | Resolves parameters + link integrity + id-remap → an ordered list of Operation Contract envelopes. Touches no filesystem. |
9
+ | `import` | plan + engine → state | Replays each envelope through the §6 engine. Idempotent. |
10
+
11
+ ```
12
+ ssss export ./vault --profile sale --out fest.ucw.json
13
+ ssss provision fest.ucw.json --param domain=acme.live --out plan.json
14
+ ssss import --plan plan.json --vault ./new-tenant
15
+ # or in one step:
16
+ ssss import fest.ucw.json --vault ./new-tenant --param domain=acme.live
17
+ ```
18
+
19
+ ## Determinism & idempotency (§17.3)
20
+
21
+ - **Id-remap.** `--prefix` relocates every file under a target path; link integrity
22
+ is checked against the remapped target, so `[[links]]` never dangle after a move.
23
+ - **Idempotency keys.** Each envelope's key is `sha256(workspace_id + ':' + path)`,
24
+ truncated. Re-importing the same plan commits nothing new — `import` reports the
25
+ unchanged count.
26
+ - **Link integrity.** `provision` fails closed if any `[[ref]]` points at a file not
27
+ present in the bundle.
28
+
29
+ ## Provisioning steps & binding vocabulary (§17.2)
30
+
31
+ `manifest.provisioning[]` describes the real-world resources an importer must wire up.
32
+ Each step: `{ id, label, system, mode, required }`.
33
+
34
+ - `system ∈ workspace | branding | email | phone | domains | accounts | deployments | marketplace | tabs | automation`
35
+ - `mode ∈ existing | provision | install | generate | configure`
36
+
37
+ Graph edges use relations like `uses_brand`, `owns_domain`, `routes_calls_to`,
38
+ `deploys_to`, `installs_pack`. Composition across bundles uses `installMode ∈
39
+ optional | recommended | required`; upgrades are structural-only via `migration` +
40
+ `patch`.
41
+
42
+ Commands: `ssss provision`, `ssss import`.
43
+ See also: `ssss help bundle`, `ssss help portability`.
@@ -0,0 +1,61 @@
1
+ # Security roles & RBAC (spec §5.4 security_role, §6.3 Stage 5.5)
2
+
3
+ Every write goes through Stage 5.5 — Granular Authorization — after content
4
+ validation and before commit. It's fail-closed: a write with no verified
5
+ `actor.role` is denied, never silently promoted to a default role.
6
+
7
+ ## The `security_role` primitive
8
+
9
+ ```markdown
10
+ ---
11
+ type: security_role
12
+ name: "editor"
13
+ permissions:
14
+ - "write:workflow"
15
+ - "write:assistant"
16
+ - "read:*"
17
+ ---
18
+
19
+ Can edit workflows and assistants; read-only on everything else.
20
+ ```
21
+
22
+ Canonical location: `roles/<role>/ROLE.md`, where `<role>` matches the
23
+ `name` field. `permissions` is a flat list — see the grammar below.
24
+
25
+ ## Permission grammar
26
+
27
+ | Pattern | Grants |
28
+ |---|---|
29
+ | `write:<type>` | Write access to exactly one primitive type. |
30
+ | `read:<type>` | Read access to exactly one primitive type. |
31
+ | `*:<type>` | Read + write on exactly one primitive type. |
32
+ | `write:*` | Write access to every primitive type, including `event`. |
33
+ | `read:*` | Read access to every primitive type. |
34
+ | `*:*` | Full access. |
35
+
36
+ `event` envelopes have no resolved document type, so they're gated on the
37
+ fixed permission `write:event` specifically — `write:<some other type>`
38
+ does **not** satisfy it, and neither does an unrelated wildcard scoped to a
39
+ document type.
40
+
41
+ ## The three non-negotiable role behaviors
42
+
43
+ | `actor.role` | Behavior |
44
+ |---|---|
45
+ | `"system"` | Unconditional bypass. Used by trusted internal callers (the provisioning pipeline stamps every generated envelope this way — see `ssss help provisioning`). Not data-driven; don't expect a `roles/system/ROLE.md`. |
46
+ | `"admin"` | Hardcoded `write:*`/`read:*`, regardless of `roles/admin/ROLE.md`'s content (a file there can only add to this, never restrict it). |
47
+ | *(absent)* | **Denied.** A host that exposes the Operation Contract to untrusted clients MUST overwrite `actor` with verified session identity before the envelope reaches the engine (spec §6.3 Stage 3). A missing `actor.role` is not a default — it's an authorization failure. |
48
+
49
+ Any other role name is resolved by reading `roles/<role>/ROLE.md` from the
50
+ target vault at write time. No file there means zero permissions.
51
+
52
+ ## Auditing this yourself
53
+
54
+ The `rbac-fail-open-auditor` agent skill (`.agent/skills/rbac-fail-open-auditor/`)
55
+ builds an adversarial envelope matrix and runs it against the reference
56
+ engine to catch regressions in this logic — including the specific
57
+ historical bug it's named after (a fail-open default that briefly shipped
58
+ in this repo's own uncommitted history; see that skill's
59
+ `references/stage-5-5-rbac-notes.md` for the full case study).
60
+
61
+ See also: `ssss help portability`, `ssss help bundle`.
@@ -0,0 +1,78 @@
1
+ # Workflow runtime (spec §11.8)
2
+
3
+ SSSS workflows are runtime definitions, not cron jobs stored somewhere else. The
4
+ canonical schedule lives in the `workflow` primitive's `triggers[]` frontmatter.
5
+ Cron, systemd, serverless schedules, webhooks, browser alarms, and queue workers
6
+ are wake-up mechanisms.
7
+
8
+ ## Canonical loop
9
+
10
+ ```
11
+ workflow trigger
12
+ -> workflow_triggered event envelope
13
+ -> task operation envelope
14
+ -> task lease / worker claim
15
+ -> run operation or append
16
+ -> task status patch
17
+ -> projection rebuild
18
+ ```
19
+
20
+ Every mutation goes through the Operation Contract. A daemon MUST NOT write vault
21
+ files directly.
22
+
23
+ ## Trigger source of truth
24
+
25
+ ```yaml
26
+ ---
27
+ type: workflow
28
+ name: "Daily Digest"
29
+ triggers:
30
+ - type: cron
31
+ id: daily-0800
32
+ cron: "0 8 * * *"
33
+ timezone: "America/Denver"
34
+ misfire_policy: run_once
35
+ concurrency: skip_if_running
36
+ isActive: true
37
+ ---
38
+ ```
39
+
40
+ Supported trigger types are `manual`, `cron`, `interval`, `event`, `webhook`,
41
+ `file_change`, and `condition`.
42
+
43
+ ## Idempotency
44
+
45
+ Runtime-created work uses this dedupe basis:
46
+
47
+ ```text
48
+ workspace_id + workflow_id + trigger_id + scheduled_for
49
+ ```
50
+
51
+ Two daemon ticks for the same scheduled instant MUST produce the same task
52
+ idempotency key. This is how SSSS avoids duplicate tasks without making a scheduler
53
+ database canonical.
54
+
55
+ ## Reference helpers
56
+
57
+ Use `@ssss/cli/runtime` when building a host daemon:
58
+
59
+ ```js
60
+ import { createEngine } from '@ssss/cli/engine';
61
+ import { planWorkflowTrigger } from '@ssss/cli/runtime';
62
+
63
+ const plan = planWorkflowTrigger({
64
+ workflowPath: 'workflows/daily-digest/WORKFLOW.md',
65
+ workflowContent,
66
+ workspaceId: 'ws-1',
67
+ trigger: { type: 'cron', id: 'daily-0800', cron: '0 8 * * *' },
68
+ scheduledFor: '2026-07-02T14:00:00.000Z',
69
+ });
70
+
71
+ const engine = createEngine();
72
+ for (const envelope of plan.envelopes) {
73
+ engine.processOperation(envelope, './vault');
74
+ }
75
+ ```
76
+
77
+ `ssss conformance --engine` includes runtime checks that prove deterministic task
78
+ planning, idempotent duplicate ticks, and run creation through the reference engine.
@@ -0,0 +1,47 @@
1
+ # `ssss new` — scaffold a project
2
+
3
+ Create a fresh, ready-to-run repo wired for SSSS (and optionally Total Recall).
4
+
5
+ ```bash
6
+ ssss new my-app # scaffold ./my-app
7
+ ssss new my-app --install # also npm install + run the conformance test
8
+ ssss new my-app --with-total-recall # also wire the Total Recall memory OS
9
+ ssss new my-app --with-total-recall --install
10
+ ```
11
+
12
+ ## What you get
13
+
14
+ ```
15
+ my-app/
16
+ package.json @ssss/cli pinned to this CLI's version tag; npm test = node --test
17
+ vault/ Starter SSSS documents:
18
+ rules/welcome.md (structural)
19
+ workflows/onboarding.md (structural, links [[welcome]])
20
+ assistants/concierge.md (structural)
21
+ tasks/first-task.md (tenant_private — dropped from sale/template exports)
22
+ test/ssss-conformance.test.mjs Replays the canonical fixtures through the engine
23
+ AND round-trips the vault as a sale bundle.
24
+ CLAUDE.md Agent guide (source-of-truth + portability rules).
25
+ README.md .gitignore
26
+ ```
27
+
28
+ The generated test is **dependency-free** (`node --test`): it proves the toolchain
29
+ implements the Operation Contract (§6) and that the starter vault exports, validates,
30
+ provisions, and re-imports idempotently as a `sale` bundle (§16/§17) — with the
31
+ `tenant_private` task correctly dropped.
32
+
33
+ ## Flags
34
+
35
+ | Flag | Effect |
36
+ |------|--------|
37
+ | `--name <s>` | Package name (default: the directory name). |
38
+ | `--with-total-recall` | Add `total-recall-brain` + memory wiring to CLAUDE.md/README. |
39
+ | `--install` | Run `npm install`, Total Recall `init` (if requested), then `npm test`. |
40
+ | `--no-git` | Skip `git init`. |
41
+ | `--ref <git-ref>` | Pin `@ssss/cli` to a specific tag/branch/SHA (default: this CLI's version tag). |
42
+ | `--force` | Scaffold into a non-empty directory. |
43
+
44
+ Shelling out (git/npm/npx) uses `execFileSync` with fixed argument vectors — no shell,
45
+ no interpolation.
46
+
47
+ See also: `ssss help portability`, `ssss help provisioning`, `ssss export`.