total-recall-brain 3.9.0 → 3.11.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 (49) hide show
  1. package/bin/antigravity.mjs +62 -183
  2. package/package.json +6 -5
  3. package/scaffold/.agent/skills/total-recall/SKILL.md +1 -0
  4. package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/SKILL.md +3 -2
  5. package/scaffold/.agent/skills/total-recall/skills/{research → tr-research}/SKILL.md +2 -1
  6. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/SKILL.md +3 -2
  7. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/evals/evals.json +3 -3
  8. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/hooks/on-skill-add.sh +1 -1
  9. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/hooks/on-skill-delete.sh +1 -1
  10. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/scripts/create-skill.sh +3 -3
  11. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/scripts/find-skills.mjs +25 -1
  12. package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/install-skill.mjs +117 -0
  13. package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/scripts/scan-skill.mjs +20 -0
  14. package/scaffold/.agent/skills/total-recall/skills/{ssss → tr-ssss}/SKILL.md +120 -19
  15. package/scaffold/.agent/skills/total-recall/skills/tr-ssss/references/CHANGELOG.md +124 -0
  16. package/scaffold/.agent/skills/total-recall/skills/{ssss → tr-ssss}/references/ssss-spec.md +474 -43
  17. package/src/cli/connect.mjs +6 -59
  18. package/src/cli/ingest-openwiki.mjs +122 -0
  19. package/src/cli/ingest.mjs +9 -0
  20. package/src/cli/init.mjs +42 -2
  21. package/src/cli/skill-projection.mjs +214 -0
  22. package/src/cli/skill.mjs +44 -18
  23. package/src/core/daemon-loop.mjs +13 -2
  24. package/src/core/operation-validator.mjs +85 -9
  25. package/src/core/research.mjs +47 -9
  26. package/src/core/runtime.mjs +14 -7
  27. package/src/core/schema.mjs +85 -13
  28. package/src/server/api.mjs +2 -2
  29. package/src/server/rest.mjs +3 -3
  30. package/src/server/routes/skills.mjs +25 -4
  31. package/scaffold/.agent/skills/total-recall/skills/ssss/references/CHANGELOG.md +0 -9
  32. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/agents.yml +0 -0
  33. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/evals/.gitkeep +0 -0
  34. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/references/antigravity.txt +0 -0
  35. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/references/claude.txt +0 -0
  36. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/references/codex.txt +0 -0
  37. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/references/gemini.txt +0 -0
  38. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/scripts/.gitkeep +0 -0
  39. /package/scaffold/.agent/skills/total-recall/skills/{cli-agents → tr-cli-agents}/subagents/.gitkeep +0 -0
  40. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/assets/skill-template/SKILL.md +0 -0
  41. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/learnings/.gitkeep +0 -0
  42. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/references/.gitkeep +0 -0
  43. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/scripts/.gitkeep +0 -0
  44. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/scripts/enforce-skill-optimization.mjs +0 -0
  45. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/scripts/skill-watcher.mjs +0 -0
  46. /package/scaffold/.agent/skills/total-recall/skills/{skill → tr-skill}/subagents/audit-all-skills.md +0 -0
  47. /package/scaffold/.agent/skills/total-recall/skills/{ssss → tr-ssss}/evals/evals.json +0 -0
  48. /package/scaffold/.agent/skills/total-recall/skills/{ssss → tr-ssss}/scripts/validate-schema.mjs +0 -0
  49. /package/scaffold/.agent/skills/total-recall/skills/{ssss → tr-ssss}/subagents/audit-ssss-node.md +0 -0
@@ -1,6 +1,6 @@
1
1
  # SSSS — Structured Semantic Syntax System
2
2
 
3
- **Specification v0.2 — Draft**
3
+ **Specification v0.6 — Draft**
4
4
 
5
5
  > This is the canonical, vendor-neutral specification for SSSS. It is the ground
6
6
  > truth on which all SSSS implementations are built. It is intended to be vendored
@@ -22,19 +22,19 @@ SSSS — the Structured Semantic Syntax System — is a **database-free, Markdow
22
22
  schema and mutation contract for AI agent state**.
23
23
 
24
24
  Every unit of agent-relevant state — a memory, a skill, a conversation, a workflow
25
- run, an assistant definition — is a plain Markdown file with YAML frontmatter. There
26
- is no relational database of record, no binary format, and no proprietary container.
27
- A relational store MAY exist, but only as a *disposable projection* rebuildable from
28
- the Markdown.
25
+ run, an assistant definition, a runtime task — is a plain Markdown file with YAML
26
+ frontmatter. There is no relational database of record, no binary format, and no
27
+ proprietary container. A relational store MAY exist, but only as a *disposable
28
+ projection* rebuildable from the Markdown.
29
29
 
30
30
  SSSS additionally defines the **Operation Contract**: a single, validated, idempotent
31
31
  envelope through which all agent-generated mutations must flow. This makes
32
32
  AI-generated state changes deterministic, replayable, conflict-safe, and auditable.
33
33
 
34
- Any tool, IDE, agent framework, or CLI that can read Markdown can interoperate with
35
- an SSSS vault. The only thing that distinguishes a memory engine, a chat runtime, and
36
- a workflow orchestrator is *which primitive types they read and write* — the
37
- underlying file format and mutation contract are identical.
34
+ Any tool, IDE, agent framework, daemon, or CLI that can read Markdown can
35
+ interoperate with an SSSS vault. The only thing that distinguishes a memory engine,
36
+ a chat runtime, and a workflow orchestrator is *which primitive types they read and
37
+ write* — the underlying file format and mutation contract are identical.
38
38
 
39
39
  ---
40
40
 
@@ -112,13 +112,30 @@ Every SSSS document primitive MUST include:
112
112
  | Field | Type | Description |
113
113
  |-------|------|-------------|
114
114
  | `type` | string | The primitive type. MUST match an entry in the Type Registry (§5). |
115
+ | `title` | string | Human-readable title of the document. |
116
+ | `description` | string | One-sentence summary of the document's purpose. |
117
+ | `timestamp` | string | ISO 8601 timestamp of last modification. |
118
+
119
+ For OKF-compatible discovery, SSSS document primitives SHOULD also include:
120
+
121
+ | Field | Type | Description |
122
+ |-------|------|-------------|
123
+ | `resource` | string | Canonical URI for the underlying asset, when the primitive describes one. |
124
+ | `tags` | array | Array of string tags for categorization and routing. |
125
+ | `aliases` | array | Array of alternative names for this concept, used for wiki autolinking. |
115
126
 
116
127
  Every primitive type defines its own additional REQUIRED and OPTIONAL fields
117
- (§5.4). Hosts MUST NOT invent required fields outside this spec; host-specific
118
- fields are permitted only as OPTIONAL fields and SHOULD be namespaced (e.g.
119
- `x_host_*`) to avoid collision with future spec fields.
128
+ (§5.4). To maintain forward compatibility and allow agents scratchpad space, hosts MUST NOT reject documents containing unknown frontmatter keys. Unknown fields MUST be preserved.
120
129
 
121
- ### 4.3 Canonical Filenames
130
+ ### 4.3 Linking & Progressive Disclosure
131
+
132
+ SSSS adopts the OKF standards for hyperlinking and directory indices:
133
+
134
+ 1. **Absolute Bundle-Relative Links**: Links to other primitives SHOULD be absolute paths starting from the vault root (e.g., `[Customer Assistant](/assistants/support.md)`).
135
+ 2. **The `# Citations` Section**: If a primitive's body makes claims sourced from other primitives or external data, it SHOULD include a `# Citations` heading at the bottom with numbered reference links.
136
+ 3. **Index Files (`index.md`)**: A host MAY generate `index.md` files in directories to provide progressive disclosure of the vault's contents. These files contain no frontmatter and exist solely to serve as a table of contents for agents traversing the VFS.
137
+
138
+ ### 4.4 Canonical Filenames
122
139
 
123
140
  Document primitives that have a fixed role in a directory use an **uppercase
124
141
  canonical filename** that signals the primitive at a glance:
@@ -147,21 +164,26 @@ primitive — it implements the subset its product requires — but any primitiv
147
164
 
148
165
  ### 5.1 Document Primitives
149
166
 
150
- | `type` | Family | Purpose |
151
- |--------|--------|---------|
152
- | `memory` | knowledge | A single unit of agent knowledge (rule, pattern, fact, preference). |
153
- | `skill` | capability | A skill package manifest. |
154
- | `rule` | governance | A workspace-scoped behavior rule applied to assistants/agents. |
155
- | `task` | work | A unit of submitted work — one step or many. The universal work primitive. |
156
- | `assistant` | actor | The definition of an AI assistant/persona. |
157
- | `workflow` | work | A reusable **task template**: a defined procedure plus triggers. Firing a workflow submits a `task`. |
158
- | `model` | catalog | The definition of an inference model. |
159
- | `conversation` | transcript | An append-only chat transcript. |
160
- | `run` | transcript | An append-only workflow execution record. |
161
- | `conflict` | meta | A record of two contradicting primitives, blocking promotion. |
162
- | `page` | capability | A VFS-native sandboxed custom workspace page. |
163
- | `migration` | meta | An SSSS schema migration state record. |
164
- | `release` | meta | An SSSS system schema version release record. |
167
+ | `type` | Family | Portability | Purpose |
168
+ |--------|--------|-------------|---------|
169
+ | `memory` | knowledge | structural | A single unit of agent knowledge (rule, pattern, fact, preference). |
170
+ | `skill` | capability | structural | A skill package manifest. |
171
+ | `rule` | governance | structural | A workspace-scoped behavior rule applied to assistants/agents. |
172
+ | `security_role` | governance | structural | A security role definition for role-based access control (RBAC). |
173
+ | `task` | work | tenant_private | A unit of submitted work — one step or many. The universal work primitive. |
174
+ | `assistant` | actor | structural | The definition of an AI assistant/persona. |
175
+ | `workflow` | work | structural | A reusable **task template**: a defined procedure plus triggers. Firing a workflow submits a `task`. |
176
+ | `model` | catalog | structural | The definition of an inference model. |
177
+ | `conversation` | transcript | tenant_private | An append-only chat transcript. |
178
+ | `run` | transcript | tenant_private | An append-only workflow execution record. |
179
+ | `conflict` | meta | tenant_private | A record of two contradicting primitives, blocking promotion. |
180
+ | `page` | capability | structural | A VFS-native sandboxed custom workspace page. |
181
+ | `migration` | meta | structural | An SSSS schema migration state record. |
182
+ | `release` | meta | structural | An SSSS system schema version release record. |
183
+
184
+ The **Portability** column is the primitive's default portability class (§5.5); a host
185
+ resolves it from `registry/core.json`. Extension registries assign their own primitives a
186
+ class — notably `resource_bound` for things like domains and phone numbers.
165
187
 
166
188
  ### 5.2 Contract Primitives
167
189
 
@@ -170,6 +192,7 @@ primitive — it implements the subset its product requires — but any primitiv
170
192
  | `operation` | A full atomic file write (create or full replace) — see §6. |
171
193
  | `patch` | A partial merge into an existing file — see §6. |
172
194
  | `event` | An append-only immutable log entry — see §6, §8. |
195
+ | `delete` | A tombstoning removal of a replace-type file — see §6. |
173
196
  | `lease` | A file-level write lock — see §7. |
174
197
 
175
198
  ### 5.3 Append-Type vs. Replace-Type Documents
@@ -262,12 +285,21 @@ REQUIRED: `type`, `priority` (integer), `category`, `status`
262
285
  (`pending|in_progress|done|failed`). A task instantiated from a template carries an
263
286
  OPTIONAL `workflow_id` referencing it.
264
287
 
288
+ Runtime-created tasks SHOULD additionally carry `workflow_path`, `trigger_id`,
289
+ `trigger_type`, `trigger_event_id`, `scheduled_for`, and `dedupe_key`. These fields
290
+ make the task reconstructible from the workflow definition plus the trigger event
291
+ and prevent duplicate daemon ticks from creating duplicate work (§11.8).
292
+
265
293
  ```markdown
266
294
  ---
267
295
  type: task
268
296
  priority: 85
269
297
  category: skill-engineering
270
298
  status: pending
299
+ workflow_id: "research-skill"
300
+ trigger_id: "manual"
301
+ scheduled_for: 2026-05-16T08:00:00Z
302
+ dedupe_key: "runtime:abc123"
271
303
  ---
272
304
 
273
305
  ## Objective
@@ -303,6 +335,20 @@ the submitted instance.
303
335
  REQUIRED: `type`, `name`. `triggers` (array) is OPTIONAL — a workflow with no
304
336
  triggers is valid and may be invoked manually or by another workflow.
305
337
 
338
+ When present, `triggers[]` is the canonical schedule source. OS cron, hosted
339
+ schedulers, queues, and daemon timers are wake-up mechanisms only; they MUST NOT
340
+ become the record of what the workflow schedule means. A trigger entry SHOULD
341
+ include:
342
+
343
+ | Field | Description |
344
+ |-------|-------------|
345
+ | `type` | `manual`, `cron`, `interval`, `event`, `webhook`, `file_change`, or `condition`. |
346
+ | `id` / `trigger_id` | Stable trigger identity within the workflow. |
347
+ | `cron` / `interval` / `event_type` | Type-specific selector. |
348
+ | `timezone` | Required for wall-clock schedules; UTC is implied if omitted. |
349
+ | `misfire_policy` | `skip`, `run_once`, or `catch_up`; default `run_once`. |
350
+ | `concurrency` | `allow_parallel`, `skip_if_running`, `enqueue`, or `replace`; default `skip_if_running`. |
351
+
306
352
  ```markdown
307
353
  ---
308
354
  type: workflow
@@ -310,7 +356,11 @@ name: "Daily Digest"
310
356
  description: "Sends a daily summary email."
311
357
  triggers:
312
358
  - type: cron
359
+ id: daily-0800
313
360
  cron: "0 8 * * *"
361
+ timezone: "America/Denver"
362
+ misfire_policy: run_once
363
+ concurrency: skip_if_running
314
364
  isActive: true
315
365
  ---
316
366
 
@@ -339,6 +389,27 @@ scope: support
339
389
  Outbound links are stripped from any assistant reply on a support thread.
340
390
  ```
341
391
 
392
+ #### `security_role`
393
+
394
+ A definition of a security role used for role-based access control (RBAC).
395
+ It maps a role name to a set of permissions that dictate what an agent or user
396
+ can do within the workspace.
397
+
398
+ REQUIRED: `type`, `name`, `permissions` (array). OPTIONAL: `description`.
399
+
400
+ ```markdown
401
+ ---
402
+ type: security_role
403
+ name: "admin"
404
+ description: "Administrator with full access to all workspace primitives."
405
+ permissions:
406
+ - "read:*"
407
+ - "write:*"
408
+ ---
409
+
410
+ Full administrative access to the workspace.
411
+ ```
412
+
342
413
  #### `model`
343
414
 
344
415
  The definition of an inference model.
@@ -386,14 +457,18 @@ Hi — how can I help?
386
457
  An append-only workflow execution record. Append-type.
387
458
 
388
459
  REQUIRED: `type`, `run_id`, `workflow_id`. Typical fields: `workspace_id`, `status`,
389
- `step_count`, `started_at`.
460
+ `task_id`, `task_path`, `step_count`, `started_at`.
461
+
462
+ `status` SHOULD be one of: `queued`, `claimed`, `running`, `waiting_for_human`,
463
+ `succeeded`, `failed`, `canceled`, `retrying`, `dead_letter`.
390
464
 
391
465
  ```markdown
392
466
  ---
393
467
  type: run
394
468
  run_id: "run-001"
395
469
  workflow_id: "daily-digest"
396
- status: running
470
+ task_path: "tasks/daily-digest/daily-0800-20260516T080000Z.md"
471
+ status: queued
397
472
  started_at: 2026-05-16T08:00:00Z
398
473
  ---
399
474
 
@@ -470,6 +545,41 @@ released_at: 2026-05-16T12:00:00Z
470
545
  ---
471
546
  ```
472
547
 
548
+ ### 5.5 Portability Classification
549
+
550
+ A workspace is not one undifferentiated blob. Some of it is the **reusable business
551
+ model** (the workflows, assistants, pages, and rules that make the business run); some is
552
+ the operator's **private operational data** (customer transcripts, runtime work); and some
553
+ is **bound to a real external resource** (a domain, a phone number, a mailbox). Selling,
554
+ templating, and backing up a workspace each need a different slice. SSSS makes that slice
555
+ declarable instead of ad-hoc.
556
+
557
+ Every **document** primitive declares one **portability class** in its registry entry.
558
+ (Contract primitives — `operation`/`patch`/`event`/`lease` — are protocol envelopes, not
559
+ stored documents, and have no portability class.)
560
+
561
+ | Class | Meaning | May appear in template/sale? |
562
+ |-------|---------|------------------------------|
563
+ | `structural` | The reusable business model — carries no operator- or customer-specific data. | ✅ verbatim |
564
+ | `tenant_private` | The operator's private operational data (customers, transcripts, runtime work). | ❌ never — backup only, encrypted at rest |
565
+ | `resource_bound` | Requires a real external resource bound at provision time. | ⚠️ as a **requirement declaration** only — the seller's resource value is stripped |
566
+
567
+ A file MAY override its type's default with an `x_portability` frontmatter field. A host
568
+ MUST honor the **most restrictive** of (type default, instance override) — a file may make
569
+ itself more private than its type, never less.
570
+
571
+ An **export profile** is simply a filter over portability classes:
572
+
573
+ - **`backup`** — all three classes. `tenant_private` MUST be encrypted at rest.
574
+ - **`template`** / **`sale`** — `structural` verbatim; `resource_bound` reduced to a
575
+ requirement declaration (seller's bound value stripped); `tenant_private` **dropped
576
+ entirely**.
577
+
578
+ A host MUST reject a `template`/`sale` export that would emit a `tenant_private` primitive.
579
+ This single rule is what lets an operator sell a proven business model without ever
580
+ shipping a customer's data — the data is `tenant_private` by classification, so it
581
+ physically cannot enter a sale bundle.
582
+
473
583
  ---
474
584
 
475
585
  ## 6. The Operation Contract
@@ -483,7 +593,7 @@ An operation is a JSON envelope:
483
593
 
484
594
  ```jsonc
485
595
  {
486
- "type": "operation", // "operation" | "patch" | "event"
596
+ "type": "operation", // "operation" | "patch" | "event" | "delete"
487
597
  "idempotency_key": "uuid-v4", // see §6.4
488
598
  "path": "assistants/bot/ASSISTANT.md", // relative VFS path, no leading "/"
489
599
  "workspace_id": "uuid", // the vault/workspace scope
@@ -491,7 +601,11 @@ An operation is a JSON envelope:
491
601
  "patches": { }, // partial merge (patch only)
492
602
  "lease_id": "uuid", // OPTIONAL — see §7
493
603
  "intent": "human description", // OPTIONAL — audit annotation
494
- "dry_run": false // OPTIONAL — validate without committing
604
+ "dry_run": false, // OPTIONAL — validate without committing
605
+ "actor": { // OPTIONAL — the cryptographically verified identity.
606
+ "type": "human", // "human" | "ai" | "system"
607
+ "role": "admin" // role-based access control hook for the host
608
+ }
495
609
  }
496
610
  ```
497
611
 
@@ -502,29 +616,58 @@ An operation is a JSON envelope:
502
616
  | `operation` | Full atomic write — creates or fully replaces a file. | `content` | `type`, `idempotency_key`, `path`, `workspace_id`, `content` |
503
617
  | `patch` | Partial merge into an existing file's frontmatter and/or body. | `patches` | `type`, `idempotency_key`, `path`, `workspace_id`, `patches` |
504
618
  | `event` | Append-only immutable log entry. Never overwrites. | `content` | `type`, `idempotency_key`, `path`, `workspace_id`, `content` |
619
+ | `delete` | Removes a replace-type file from the vault. | — | `type`, `idempotency_key`, `path`, `workspace_id` |
505
620
 
506
621
  For `patch`, the `patches` object merges into frontmatter keys; the reserved key
507
622
  `__body__` replaces or (for append-type documents) appends the Markdown body. For
508
623
  `event`, `content` MUST be a valid JSON string carrying the event payload.
509
624
 
625
+ For `delete`, the host removes the file at `path` and appends a deletion event to the log
626
+ (§8) — the removal is itself an auditable, append-only record, so history is never lost. A
627
+ host MUST reject a `delete` targeting an **append-type** document (`conversation`, `run`)
628
+ or a non-existent path. A `delete` of an already-deleted path is an idempotent no-op that
629
+ returns the original result (§6.4). `delete` is the only contract type that removes vault
630
+ state; export and provision (§16) never delete — only a live workspace edit or a migration
631
+ (§5.4 `migration`) does.
632
+
510
633
  ### 6.3 The Processing Pipeline
511
634
 
512
635
  A host MUST process every operation through these ordered stages. Any stage's
513
636
  failure aborts the operation with no commit.
514
637
 
515
- 1. **Envelope validation** — `type` is one of the three envelope types; required
516
- envelope fields present and well-formed.
517
- 2. **Idempotency check** — if this `idempotency_key` + `workspace_id` was already
518
- committed within the TTL, return the original result as a replay (§6.4). Stop.
519
- 3. **Authorization** — the agent has write access to `workspace_id`.
638
+ 1. **Envelope validation** — `type` is one of the four envelope types
639
+ (`operation`/`patch`/`event`/`delete`); required envelope fields present and
640
+ well-formed.
641
+ 2. **Idempotency check** — if this `idempotency_key` + `workspace_id` +
642
+ request hash was already committed within the TTL, return the original result
643
+ as a replay (§6.4). If the key and workspace match but the request hash
644
+ differs, reject the request with `idempotency_conflict`. Stop.
645
+ 3. **Authorization & Actor Identity** — the agent has write access to `workspace_id`.
646
+ *Security Mandate*: If a host exposes the Operation Contract directly to untrusted clients (e.g., a `POST /api/ssss` REST endpoint), the host **MUST** irreversibly overwrite the `actor` payload with the user's cryptographically verified session identity. Hosts MUST use this `actor` field to enforce Role-Based Access Control (RBAC) over sensitive or `resource_bound` primitives.
520
647
  4. **Lease check** — if the target path is leased, the operation MUST carry a
521
648
  matching, unexpired `lease_id` (§7).
522
649
  5. **Content validation** — for `operation`/`patch`, the resulting file is validated
523
- against its primitive schema (§9). Append-type rewrite attempts are rejected.
524
- 6. **Commit** — the mutation is applied to the vault atomically.
650
+ against its primitive schema (§9). Append-type rewrite attempts are rejected. For
651
+ `delete`, the host verifies the target exists and is a replace-type document (append-type
652
+ deletes are rejected).
653
+ 5.5. **Granular Authorization (RBAC)** — evaluated only if stage 5 passed. Resolve
654
+ `actor.role` from the (by now host-verified, per stage 3) envelope. `role: "system"`
655
+ is an unconditional bypass (used by trusted internal callers such as the provisioning
656
+ pipeline, §17). `role: "admin"` is granted `write:*`/`read:*` unconditionally. Any
657
+ other named role's permissions are read from that role's `security_role` document
658
+ (canonical location `roles/<role>/ROLE.md`) and checked against the required
659
+ permission — `write:<type>` for `operation`/`patch`/`delete` (using the type resolved
660
+ in stage 5), or the fixed `write:event` for `event` envelopes (which have no resolved
661
+ document type). A permission list satisfies the requirement via an exact match,
662
+ `*:<type>`, `write:*`, or `*:*`. **A MISSING `actor.role` MUST be denied, not treated
663
+ as any default role** — this is the fail-closed complement to stage 3's mandate: a
664
+ host that forgets to overwrite `actor` gets every write rejected, not silently
665
+ promoted to admin.
666
+ 6. **Commit** — the mutation is applied to the vault atomically. For `delete`, the file is
667
+ removed.
525
668
  7. **Audit** — an audit entry is appended to the event log (§8).
526
669
 
527
- A `dry_run` operation runs stages 1–5 and then stops: it MUST return the validation
670
+ A `dry_run` operation runs stages 1–5.5 and then stops: it MUST return the validation
528
671
  verdict with `success` reflecting validity, and MUST NOT commit (`committed_at` is
529
672
  `null`).
530
673
 
@@ -553,9 +696,11 @@ verdict with `success` reflecting validity, and MUST NOT commit (`committed_at`
553
696
 
554
697
  | Code | Meaning |
555
698
  |------|---------|
699
+ | `400` | Invalid request — malformed envelope, or a path that fails the traversal guard. |
556
700
  | `401` | Authentication required. |
557
701
  | `403` | Agent lacks write access to the workspace. |
558
- | `409` | Lease conflict — path is locked, or the supplied lease is invalid/expired. |
702
+ | `404` | The `patch`/`delete` target does not exist. |
703
+ | `409` | Lease conflict, version conflict, or idempotency conflict — path is locked, the supplied lease is invalid/expired, or the same idempotency key was reused for a different request hash. |
559
704
  | `422` | Validation failure — see `validation.errors` and `repair`. |
560
705
  | `500` | Internal error — the operation was not committed. |
561
706
 
@@ -640,6 +785,8 @@ A file is valid if and only if:
640
785
  3. Every REQUIRED field for that primitive is present and non-empty.
641
786
  4. For append-type documents, the operation does not rewrite existing records.
642
787
 
788
+ Hosts MUST NOT reject a file due to the presence of unknown or unrecognized frontmatter keys. Unrecognized keys MUST be silently preserved to support agent scratchpads and forward compatibility with OKF extensions.
789
+
643
790
  On failure, the host MUST return structured **repair feedback** so an agent can
644
791
  self-correct without guesswork:
645
792
 
@@ -783,6 +930,123 @@ a host MUST remain fully functional with feedback collection disabled, and the
783
930
  semantic layer MUST degrade gracefully to its other signals (access frequency, decay,
784
931
  embedding similarity).
785
932
 
933
+ ### 11.7 The `language_convention` Primitive
934
+
935
+ Because the control vocabulary is symbolic and never translated (§11.1), a workspace
936
+ that wishes to *present* itself in a given human language does so with data, not by
937
+ translating keys. The `language_convention` primitive (a `structural`, extension-owned
938
+ type — festech ships it) records a workspace's presentation conventions: its default
939
+ language/locale, formality, date and currency formatting, and terminology preferences.
940
+
941
+ It is `structural` and therefore travels in `template`/`sale` bundles (§5.5): a sold
942
+ business carries its voice and locale conventions, but never the operator's private
943
+ content. A host applies a `language_convention` as a **presentation overlay** at the
944
+ semantic/rendering layer; it MUST NOT alter the deterministic layer's symbolic keys or
945
+ enumerated values.
946
+
947
+ ### 11.8 Workflow Runtime & Daemon Contract
948
+
949
+ SSSS defines the source of truth for workflow runtime behavior, but it does not
950
+ mandate one resident process manager. A host MAY use OS cron, systemd timers,
951
+ serverless schedules, webhooks, message queues, browser alarms, or an always-on
952
+ daemon to wake the runtime. Those systems are **wake-up mechanisms** only. They MUST
953
+ NOT become the canonical schedule, queue, or task history.
954
+
955
+ The canonical runtime sources are:
956
+
957
+ | Concern | Source of truth |
958
+ |---------|-----------------|
959
+ | Schedule and trigger meaning | `workflow` frontmatter `triggers[]`. |
960
+ | Submitted work | `task` documents. |
961
+ | Execution transcript | append-only `run` documents. |
962
+ | What happened | append-only event log (§8). |
963
+ | Claim/concurrency safety | leases (§7) plus deterministic idempotency keys (§6.4). |
964
+ | Dashboards, task queues, cursors | projections (§10), rebuildable from the vault and event log. |
965
+
966
+ A conformant daemon loop is:
967
+
968
+ 1. **Scan** active `workflow` primitives whose `triggers[]` might fire.
969
+ 2. **Evaluate** the trigger against wall-clock time, incoming event, webhook, file
970
+ change, condition, or explicit manual invocation.
971
+ 3. **Append** a `workflow_triggered` event via an `event` envelope.
972
+ 4. **Instantiate** one `task` via an `operation` envelope.
973
+ 5. **Claim** the task using a time-bound lease before execution.
974
+ 6. **Create or append** a `run` record for execution steps.
975
+ 7. **Patch** task status to `done` or `failed`, or to `pending` with retry metadata.
976
+ 8. **Rebuild** derived task queues, run timelines, graph indexes, or UI projections
977
+ as needed.
978
+
979
+ Every step that mutates vault state MUST use the Operation Contract (§6). A daemon
980
+ MUST NOT write task, run, cursor, or workflow files directly.
981
+
982
+ #### Trigger Types
983
+
984
+ Core trigger types are:
985
+
986
+ | Type | Fires when |
987
+ |------|------------|
988
+ | `manual` | A human, agent, or another workflow invokes it. |
989
+ | `cron` | A wall-clock cron expression reaches a scheduled instant. |
990
+ | `interval` | A fixed duration elapses after the previous scheduled instant. |
991
+ | `event` | A matching event-log entry appears. |
992
+ | `webhook` | A verified external request arrives. |
993
+ | `file_change` | A matching vault path is created, patched, or deleted. |
994
+ | `condition` | A host-defined predicate over vault/projection state becomes true. |
995
+
996
+ Trigger entries SHOULD use the fields documented in §5.4 `workflow`. Hosts MAY add
997
+ type-specific `x_` fields, but MUST preserve unknown fields when rewriting the
998
+ workflow document (§4.2).
999
+
1000
+ #### Idempotency & Duplicate Daemons
1001
+
1002
+ The idempotency basis for runtime-created work is:
1003
+
1004
+ ```text
1005
+ workspace_id + workflow_id + trigger_id + scheduled_for
1006
+ ```
1007
+
1008
+ Two daemon ticks evaluating the same trigger for the same scheduled instant MUST
1009
+ produce the same task idempotency key. Replaying the same envelope MUST NOT create a
1010
+ second task. This rule is what lets an SSSS host run multiple scheduler processes
1011
+ without a scheduler database becoming the source of truth.
1012
+
1013
+ For `event`, `webhook`, and `file_change` triggers, `scheduled_for` SHOULD be the
1014
+ canonical event timestamp or the host's normalized receipt timestamp, and the task
1015
+ SHOULD also record `trigger_event_id` when one exists.
1016
+
1017
+ #### Concurrency, Misfires & Retries
1018
+
1019
+ `misfire_policy` determines what happens when a daemon wakes after one or more missed
1020
+ schedule instants:
1021
+
1022
+ | Policy | Meaning |
1023
+ |--------|---------|
1024
+ | `skip` | Do not create work for missed instants. |
1025
+ | `run_once` | Create one task for the most recent missed instant. |
1026
+ | `catch_up` | Create one task per missed instant, each with its own idempotency key. |
1027
+
1028
+ `concurrency` determines what happens when a trigger fires while earlier work from
1029
+ the same workflow/trigger is still active:
1030
+
1031
+ | Policy | Meaning |
1032
+ |--------|---------|
1033
+ | `allow_parallel` | Create the new task regardless of active runs. |
1034
+ | `skip_if_running` | Do not create a new task while a prior run is active. |
1035
+ | `enqueue` | Create a pending task, but allow a worker to claim it only after prior work finishes. |
1036
+ | `replace` | Cancel or fail the previous task/run before creating the replacement. |
1037
+
1038
+ Retries MUST be represented on the `task` and/or `run` (`attempts`,
1039
+ `next_attempt_at`, `status: retrying`) and by events. A dead-letter outcome SHOULD be
1040
+ represented as `status: failed` on the task and `status: dead_letter` on the final
1041
+ run, plus an event explaining the terminal failure.
1042
+
1043
+ #### Runtime Helpers
1044
+
1045
+ The reference package exposes `@ssss/cli/runtime`, including deterministic helpers
1046
+ for planning a workflow trigger into a `workflow_triggered` event envelope and a
1047
+ task `operation` envelope. Hosts MAY implement their own daemon, but SHOULD pass the
1048
+ runtime conformance checks to prove the same source-of-truth and idempotency rules.
1049
+
786
1050
  ---
787
1051
 
788
1052
  ## 12. Conformance
@@ -796,13 +1060,15 @@ Fixtures are distributed as a JSON document carrying:
796
1060
  - `operation_types` — the envelope-type schemas.
797
1061
  - `idempotency` — TTL and replay behavior.
798
1062
  - `validation_rules` — envelope and content rules.
1063
+ - `runtime_contract` — trigger vocabulary and daemon idempotency rules (§11.8).
799
1064
  - `fixtures[]` — each with a `request`, an `expected_response`, and an
800
1065
  OPTIONAL `expected_http_status`.
801
1066
  - `error_codes` — the canonical code table.
802
1067
 
803
1068
  The conformance fixture set is the shared test contract between all SSSS
804
1069
  implementations. A host MUST NOT claim SSSS conformance without passing the current
805
- fixture set.
1070
+ fixture set. Hosts implementing workflow daemons SHOULD also run the reference
1071
+ runtime checks exposed by `@ssss/cli/runtime`.
806
1072
 
807
1073
  ---
808
1074
 
@@ -830,7 +1096,7 @@ opaque ID as the slug and keep the human-readable label in `title` / `name`.
830
1096
  This document is versioned independently of any host and of the conformance
831
1097
  fixture set.
832
1098
 
833
- - The spec version is stated in the document header (currently **v0.2 — Draft**).
1099
+ - The spec version is stated in the document header (currently **v0.6 — Draft**).
834
1100
  - Breaking changes to the file format, the type registry, or the Operation
835
1101
  Contract increment the spec version.
836
1102
  - Until **v1.0**, any version MAY introduce breaking changes.
@@ -878,6 +1144,171 @@ the determinism the contract layer depends on.
878
1144
 
879
1145
  ---
880
1146
 
1147
+ ## 16. The `.ucw` Bundle Format
1148
+
1149
+ A **bundle** is a single transportable file that packages a portion of a vault — its
1150
+ files plus a manifest describing what they are and what they need to run. A bundle is
1151
+ how an SSSS business or template is **backed up, shared, sold, and re-provisioned**. The
1152
+ canonical container is `package.ucw.json` (a "universal containerized workspace"); a host
1153
+ MAY additionally wrap it in a `.ucw` archive (the JSON plus any binary branding assets),
1154
+ but the JSON document is the normative artifact and is self-contained.
1155
+
1156
+ A bundle is produced by an **export** (§17) under one of the export profiles of §5.5
1157
+ (`backup | template | sale`). The profile a bundle was built under is recorded in its
1158
+ manifest and governs which portability classes (§5.5) its files may contain. A conformant
1159
+ exporter MUST NOT emit a `tenant_private` file into a `template` or `sale` bundle.
1160
+
1161
+ ### 16.1 Structure
1162
+
1163
+ A bundle is a JSON object with three top-level members:
1164
+
1165
+ ```jsonc
1166
+ {
1167
+ "manifest": { /* §16.2 — what this bundle is and needs */ },
1168
+ "branding": { /* OPTIONAL — binary assets, base64 (logo, favicon, colors, fonts) */ },
1169
+ "files": [ /* §16.4 — the SSSS files, in deterministic path order */ ]
1170
+ }
1171
+ ```
1172
+
1173
+ `files` MUST be sorted by `path` (byte order) so that two exports of the same vault state
1174
+ are identical and content-hashable (§16.3, `provenance.content_hash`).
1175
+
1176
+ ### 16.2 The Manifest
1177
+
1178
+ The manifest is the bundle's contract. It declares the bundle's identity, the SSSS version
1179
+ and extensions a host needs to consume it, the export profile, an inventory of what is
1180
+ inside, the resources it must bind at provision time, and provenance.
1181
+
1182
+ | Field | Required | Meaning |
1183
+ |-------|----------|---------|
1184
+ | `name` | yes | Human name of the bundle. |
1185
+ | `description` | yes | One-line summary. |
1186
+ | `version` | yes | The bundle's own semver, independent of the spec. |
1187
+ | `exported_at` | yes | ISO-8601 timestamp of export. |
1188
+ | `ssss_core_version` | yes | The `registry/core.json` `spec_version` the bundle targets (e.g. `"0.3"`). A host MUST refuse a bundle whose core version it does not support. |
1189
+ | `required_extensions` | yes | Array of extension registry ids the files rely on (e.g. `["festech"]`). Empty array if the bundle uses only core primitives. A host MUST refuse a bundle naming an extension it has not loaded. |
1190
+ | `export_profile` | yes | `backup` \| `template` \| `sale` — the §5.5 profile this bundle was built under. Determines the allowed portability classes. |
1191
+ | `primitive_inventory` | yes | Map of primitive `type` → count, over every file in the bundle (replaces ultrachat's hard-coded `categories`; it is registry-driven, so extension types appear automatically). |
1192
+ | `provisioning` | yes | Array of provisioning steps (§17.2) — the ordered, declarative plan for binding this bundle into a live workspace. Empty for a pure `backup` that is restored in place. |
1193
+ | `parameters` | no | Array of parameter definitions (§16.5) the importer must resolve (e.g. business name, domain). |
1194
+ | `source_workspace_id` | no | Origin workspace; OMITTED or nulled in `template`/`sale` profiles (it is operator-identifying). |
1195
+ | `file_count` | yes | Length of `files`; a cheap integrity check. |
1196
+ | `provenance` | yes | `{ content_hash, exporter, signature? }` (§16.3). |
1197
+
1198
+ `primitive_inventory` supersedes ultrachat's fixed `categories` object and `provisioning`
1199
+ supersedes its `capabilities` booleans: both are now open and registry-driven rather than a
1200
+ closed enum, so a bundle full of `festech` extension primitives inventories and provisions
1201
+ them without a spec change.
1202
+
1203
+ ### 16.3 Provenance & Integrity
1204
+
1205
+ `provenance` makes a bundle verifiable and attributable:
1206
+
1207
+ - `content_hash` — a hash (SHA-256, hex, prefixed `sha256:`) over the canonical
1208
+ serialization of `files` (path-sorted, §16.1). An importer MUST recompute it and reject
1209
+ a bundle whose files do not match. This is what makes a bundle tamper-evident and what a
1210
+ marketplace lists against.
1211
+ - `exporter` — an identifier for the tool/host that produced the bundle (`"@ssss/cli@0.3.0"`).
1212
+ - `signature` — OPTIONAL detached signature over `content_hash` for a sold bundle, so a
1213
+ buyer can verify authorship. Unsigned bundles are valid; signing is a marketplace concern.
1214
+
1215
+ ### 16.4 Files
1216
+
1217
+ Each entry of `files` is `{ path, content }`, where `content` is the full SSSS file text
1218
+ (frontmatter + body, §4). A host MAY also carry a parsed `frontmatter` object for
1219
+ convenience, but `content` is normative — on import the host re-parses `content`, so a
1220
+ divergent cached `frontmatter` is ignored. Every file's resolved portability class (§5.5,
1221
+ honoring `x_portability`) MUST be permitted by `export_profile`.
1222
+
1223
+ ### 16.5 Parameters
1224
+
1225
+ `parameters` are the values an importer must supply to turn a template into a running
1226
+ instance — the difference between "a festival in a box" and "*this* festival." The schema is
1227
+ adopted verbatim from ultrachat's `WorkspaceTemplateVariableDefinition`:
1228
+
1229
+ | Field | Meaning |
1230
+ |-------|---------|
1231
+ | `key` | Stable identifier, referenced by provisioning steps and link rewriting. |
1232
+ | `label` | Human prompt. |
1233
+ | `type` | Value type (`string`, `boolean`, `surfaces`, …). |
1234
+ | `scope` | Where the value applies (`workspace`, `automation`, `data`, …). |
1235
+ | `source` | Who supplies it: `user` \| `llm` \| `graph` \| `system`. |
1236
+ | `required` | Whether provisioning may proceed without it. |
1237
+ | `defaultValue`, `options`, `dependsOn` | Optional default, enumerated choices, and dependency keys. |
1238
+
1239
+ A `sale`/`template` bundle declares its `resource_bound` requirements (§5.5) as `parameters`
1240
+ of `source: user` or `source: system` — e.g. the phone number, domain, and mailbox a buyer
1241
+ must bind. This is how the standard guarantees a sold business says exactly what real-world
1242
+ resources it needs without shipping the seller's own.
1243
+
1244
+ ---
1245
+
1246
+ ## 17. The Provisioning Contract
1247
+
1248
+ Export, provision, and import are the three verbs that move a bundle (§16) between vaults.
1249
+ They are specified to be **deterministic** and **idempotent** so that selling, cloning, and
1250
+ restoring an SSSS business are reliable operations rather than bespoke migrations.
1251
+
1252
+ ### 17.1 The Three Verbs
1253
+
1254
+ - **export(vault, profile) → bundle** — Walk the vault, filter by the §5.5 portability rules
1255
+ for `profile`, sort files by path, compute `provenance.content_hash`, and emit a §16
1256
+ bundle. Export is **pure**: the same vault state and profile yield a byte-identical bundle.
1257
+ - **provision(bundle, parameters, target) → plan** — Resolve `parameters` (§16.5), bind the
1258
+ bundle's `resource_bound` requirements to real resources in `target`, and produce an
1259
+ ordered, replayable plan of Operation Contract envelopes (§6) plus resource bindings. A
1260
+ `dry_run` provision (mirroring §6 `dry_run`) validates and plans without committing.
1261
+ - **import(plan, target)** — Replay the plan's envelopes through the target's engine (§6.3).
1262
+ Because each envelope carries an `idempotency_key`, a re-run is a safe no-op: import is
1263
+ idempotent.
1264
+
1265
+ ### 17.2 Provisioning Steps & Binding Vocabulary
1266
+
1267
+ A manifest's `provisioning` array is an ordered list of steps. The step schema and its
1268
+ controlled vocabularies are adopted from ultrachat's `WorkspaceProvisioningStep` and
1269
+ `WorkspaceGraphEdge`:
1270
+
1271
+ A **step** is `{ id, label, system, mode, required, notes? }`:
1272
+
1273
+ - `system` — the subsystem the step acts on: `workspace | branding | email | phone |
1274
+ domains | accounts | deployments | marketplace | tabs | automation`.
1275
+ - `mode` — the canonical **binding verb**: `existing` (bind to a resource the target
1276
+ already has), `provision` (allocate a new real resource — a domain, a phone number),
1277
+ `install` (add a dependency bundle), `generate` (synthesize content), `configure` (set
1278
+ values). `mode` is how a bundle distinguishes "needs a *new* phone number" from "route to
1279
+ the operator's existing line."
1280
+
1281
+ Dependency and resource relationships between primitives are expressed with the canonical
1282
+ **edge relations**: `uses_brand | owns_domain | routes_calls_to | deploys_to | has_surface
1283
+ | contains_page | installs_pack | authenticates_account | runs_workflow`. The
1284
+ `resource_bound` primitives of §5.5 each declare which relation binds them (festech's
1285
+ `domain` → `owns_domain`, `phone_number` → `routes_calls_to`, `integration_connection` →
1286
+ `connects_to`), so an importer knows exactly what real-world binding each requires.
1287
+
1288
+ ### 17.3 Determinism, Id-Remap & Link Integrity
1289
+
1290
+ When a bundle is provisioned into a target vault, identifiers (slugs, workspace ids,
1291
+ cross-file links) are **remapped** so the imported business is a fresh, self-consistent
1292
+ instance rather than a clone aliasing the seller's ids. Remapping MUST preserve link
1293
+ integrity: every internal `[[link]]` / relative reference that resolved in the source bundle
1294
+ MUST resolve to the remapped target after import. This is the same rewrite engine the
1295
+ semantic layer's autolink (§11) uses, run with a bundle-relative id map. An importer that
1296
+ cannot resolve a link MUST fail the provision rather than emit a dangling reference.
1297
+
1298
+ ### 17.4 Composition & Upgrade
1299
+
1300
+ - **Composition** — a bundle MAY depend on other bundles. A dependency carries an
1301
+ `installMode` of `optional | recommended | required` (adopted from ultrachat's
1302
+ `WorkspaceMarketplaceRecommendation`). `provision` installs `required` dependencies before
1303
+ the bundle itself; `optional`/`recommended` are surfaced to the operator.
1304
+ - **Upgrade** — moving an installed bundle from `v2` to a `v1`-conformant shape (or any
1305
+ version step) is performed through a `migration` primitive (§5) plus **structural-only**
1306
+ `patch` envelopes (§6.2). An upgrade MUST NOT touch `tenant_private` data: it rewrites the
1307
+ structural model, never the operator's private records. This is what lets a sold business
1308
+ receive standard updates without the vendor reaching into customer data.
1309
+
1310
+ ---
1311
+
881
1312
  ## Appendix A — Reserved Frontmatter Keys
882
1313
 
883
1314
  The following frontmatter keys are reserved by this spec across all primitives and