@gregiteen/ssss-cli 0.7.0 → 0.8.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.
@@ -54,11 +54,11 @@ database canonical.
54
54
 
55
55
  ## Reference helpers
56
56
 
57
- Use `@ssss/cli/runtime` when building a host daemon:
57
+ Use `@gregiteen/ssss-cli/runtime` when building a host daemon:
58
58
 
59
59
  ```js
60
- import { createEngine } from '@ssss/cli/engine';
61
- import { planWorkflowTrigger } from '@ssss/cli/runtime';
60
+ import { createEngine } from '@gregiteen/ssss-cli/engine';
61
+ import { planWorkflowTrigger } from '@gregiteen/ssss-cli/runtime';
62
62
 
63
63
  const plan = planWorkflowTrigger({
64
64
  workflowPath: 'workflows/daily-digest/WORKFLOW.md',
@@ -13,7 +13,7 @@ ssss new my-app --with-total-recall --install
13
13
 
14
14
  ```
15
15
  my-app/
16
- package.json @ssss/cli pinned to this CLI's version tag; npm test = node --test
16
+ package.json @gregiteen/ssss-cli pinned to this CLI's version tag; npm test = node --test
17
17
  vault/ Starter SSSS documents:
18
18
  rules/welcome.md (structural)
19
19
  workflows/onboarding.md (structural, links [[welcome]])
@@ -38,7 +38,7 @@ provisions, and re-imports idempotently as a `sale` bundle (§16/§17) — with
38
38
  | `--with-total-recall` | Add `total-recall-brain` + memory wiring to CLAUDE.md/README. |
39
39
  | `--install` | Run `npm install`, Total Recall `init` (if requested), then `npm test`. |
40
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). |
41
+ | `--ref <git-ref>` | Pin `@gregiteen/ssss-cli` to a specific tag/branch/SHA (default: this CLI's version tag). |
42
42
  | `--force` | Scaffold into a non-empty directory. |
43
43
 
44
44
  Shelling out (git/npm/npx) uses `execFileSync` with fixed argument vectors — no shell,
@@ -0,0 +1,37 @@
1
+ # Semantic projection (spec §11.9)
2
+
3
+ SSSS builds a deterministic search and graph projection directly from validated
4
+ Markdown. The projection is disposable: the vault remains the only source of truth.
5
+
6
+ ```bash
7
+ ssss semantic ./vault
8
+ ssss semantic ./vault --query "refund policy" --limit 5
9
+ ssss semantic ./vault --locale es --query "política de reembolsos"
10
+ ssss semantic ./vault --locale es --out ./derived/semantic-es.json
11
+ ```
12
+
13
+ Records include stable identity, source path and hash, type, portability, surface
14
+ text, normalized Unicode tokens, and graph edges derived from `relations`, wiki
15
+ links, and Markdown links. Results use deterministic weighted lexical ranking; hosts
16
+ may fuse embeddings without replacing this interoperable baseline.
17
+
18
+ ## Privacy and output safety
19
+
20
+ Only `structural` documents are indexed by default. `tenant_private` and
21
+ `resource_bound` sources require the explicit `--include-private` option and an
22
+ authorized caller. This option can expose customer or operational data; never enable
23
+ it for a public index.
24
+
25
+ `--out` must point to a regular file outside the source vault. Writes are atomic.
26
+ Symlinked vault entries and unsafe paths fail closed.
27
+
28
+ ## Library API
29
+
30
+ ```js
31
+ import { buildSemanticIndex, searchSemanticIndex } from '@gregiteen/ssss-cli/semantic';
32
+
33
+ const index = buildSemanticIndex('./vault', { locale: 'es' });
34
+ const results = searchSemanticIndex(index, 'reembolsos', { limit: 10 });
35
+ ```
36
+
37
+ See also: `ssss help localization`.
package/docs/ssss-spec.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SSSS — Structured Semantic Syntax System
2
2
 
3
- **Specification v0.6 — Draft**
3
+ **Specification v0.7 — 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
@@ -31,6 +31,10 @@ SSSS additionally defines the **Operation Contract**: a single, validated, idemp
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
+ Its semantic projection contract turns the same canonical files into a deterministic
35
+ searchable graph, while translation overlays localize natural-language surfaces
36
+ without mutating symbolic control fields or private operational data.
37
+
34
38
  Any tool, IDE, agent framework, daemon, or CLI that can read Markdown can
35
39
  interoperate with an SSSS vault. The only thing that distinguishes a memory engine,
36
40
  a chat runtime, and a workflow orchestrator is *which primitive types they read and
@@ -124,6 +128,17 @@ For OKF-compatible discovery, SSSS document primitives SHOULD also include:
124
128
  | `tags` | array | Array of string tags for categorization and routing. |
125
129
  | `aliases` | array | Array of alternative names for this concept, used for wiki autolinking. |
126
130
 
131
+ For stable semantic identity and graph projection, documents SHOULD also include:
132
+
133
+ | Field | Type | Description |
134
+ |-------|------|-------------|
135
+ | `semantic_id` | string | Stable concept identity that survives file moves and localized presentation. |
136
+ | `relations` | array | Explicit semantic edges to other vault-relative document paths or semantic ids. |
137
+ | `locale` | string | BCP-47-style locale of the authored natural-language surface, when known. |
138
+
139
+ `resource`, `tags`, and `aliases` serve both OKF discovery and the semantic layer.
140
+ These fields are recommendations, not new universal requirements.
141
+
127
142
  Every primitive type defines its own additional REQUIRED and OPTIONAL fields
128
143
  (§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.
129
144
 
@@ -180,6 +195,7 @@ primitive — it implements the subset its product requires — but any primitiv
180
195
  | `page` | capability | structural | A VFS-native sandboxed custom workspace page. |
181
196
  | `migration` | meta | structural | An SSSS schema migration state record. |
182
197
  | `release` | meta | structural | An SSSS system schema version release record. |
198
+ | `translation` | localization | structural | A hash-bound, non-destructive localization overlay for a structural source document. |
183
199
 
184
200
  The **Portability** column is the primitive's default portability class (§5.5); a host
185
201
  resolves it from `registry/core.json`. Extension registries assign their own primitives a
@@ -201,7 +217,7 @@ Document primitives are either:
201
217
 
202
218
  - **Replace-type** — the whole file represents current state; a write replaces it
203
219
  entirely (`memory`, `skill`, `assistant`, `workflow`, `model`, `task`,
204
- `conflict`).
220
+ `conflict`, `translation`).
205
221
  - **Append-type** — the file is an ordered, append-only log; writes add records to
206
222
  the body and MUST NOT rewrite prior records (`conversation`, `run`).
207
223
 
@@ -545,6 +561,49 @@ released_at: 2026-05-16T12:00:00Z
545
561
  ---
546
562
  ```
547
563
 
564
+ #### `translation`
565
+
566
+ A non-destructive localization overlay for one structural source document. A
567
+ translation is itself `structural`, but it does not replace or fork the source. The
568
+ source remains authoritative for identity, behavior, permissions, enums, links, and
569
+ all other symbolic control fields.
570
+
571
+ REQUIRED: `type`, `translation_id`, `source_path`, `source_hash`, `locale`, `status`
572
+ (`draft|reviewed|approved`), and `translated_fields` (a subset of
573
+ `title|description|body`). OPTIONAL: `translated_title`, `translated_description`,
574
+ `translator`, `reviewed_at`. The Markdown body is the translated body when
575
+ `translated_fields` includes `body`.
576
+
577
+ `translation_id`, `source_path`, and `locale` are immutable after creation.
578
+ `source_path` MUST be a safe, vault-relative path to an existing `structural`
579
+ document whose type is not `translation`. `source_hash` MUST equal the source's
580
+ current SHA-256 content hash, written as `sha256:<64 lowercase hex characters>`.
581
+ A stale, missing, private, resource-bound, recursive, traversing, or symlinked source
582
+ MUST be rejected.
583
+
584
+ ```markdown
585
+ ---
586
+ type: translation
587
+ title: "Política de reembolsos — español"
588
+ description: "Traducción al español de la política de reembolsos."
589
+ timestamp: 2026-07-10T00:00:00Z
590
+ translation_id: refund-policy-es
591
+ source_path: rules/refund-policy.md
592
+ source_hash: sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
593
+ locale: es
594
+ status: approved
595
+ translated_fields: [title, description, body]
596
+ translated_title: "Política de reembolsos"
597
+ translated_description: "Reglas de reembolso para compradores."
598
+ ---
599
+
600
+ Los reembolsos están disponibles dentro de los treinta días.
601
+ ```
602
+
603
+ Draft and reviewed translations MAY be stored and previewed, but only approved,
604
+ hash-current overlays are applied by default to canonical localized projections
605
+ (§11.9).
606
+
548
607
  ### 5.5 Portability Classification
549
608
 
550
609
  A workspace is not one undifferentiated blob. Some of it is the **reusable business
@@ -1042,11 +1101,50 @@ run, plus an event explaining the terminal failure.
1042
1101
 
1043
1102
  #### Runtime Helpers
1044
1103
 
1045
- The reference package exposes `@ssss/cli/runtime`, including deterministic helpers
1104
+ The reference package exposes `@gregiteen/ssss-cli/runtime`, including deterministic helpers
1046
1105
  for planning a workflow trigger into a `workflow_triggered` event envelope and a
1047
1106
  task `operation` envelope. Hosts MAY implement their own daemon, but SHOULD pass the
1048
1107
  runtime conformance checks to prove the same source-of-truth and idempotency rules.
1049
1108
 
1109
+ ### 11.9 Semantic Projection & Localization Contract
1110
+
1111
+ The semantic layer is a **derived projection** over validated vault documents. It
1112
+ MUST be deterministic for the same vault bytes, registry set, locale, and projection
1113
+ options. It MUST NOT become a second source of truth.
1114
+
1115
+ Each projected record SHOULD expose a stable identity, source path and content hash,
1116
+ primitive type, portability class, surface text, normalized search tokens, and graph
1117
+ edges. Identity is resolved from `semantic_id`, then `resource`, then the source path.
1118
+ Edges are derived from explicit `relations`, wiki links, and Markdown links. Hosts MAY
1119
+ add embeddings or richer ranking, but the exact lexical/graph projection MUST remain
1120
+ available as a dependency-free interoperability baseline.
1121
+
1122
+ The safe default projection contains only `structural` documents. It MUST exclude
1123
+ `tenant_private` and `resource_bound` documents unless the caller explicitly enables
1124
+ private indexing in an authorized context. A localized export MUST use the same safe
1125
+ default, so requesting a locale can never implicitly disclose conversations, runs,
1126
+ tasks, credentials, customer data, or bound resource values.
1127
+
1128
+ When a locale is requested, the host MAY apply one eligible `translation` (§5.4) per
1129
+ source. Eligibility requires all of the following:
1130
+
1131
+ 1. The overlay locale normalizes to the requested locale.
1132
+ 2. Its status is `approved`, unless a caller explicitly opts into draft preview.
1133
+ 3. The source is an existing, non-symlinked `structural` document.
1134
+ 4. `source_hash` exactly matches the current source bytes.
1135
+ 5. There is no second eligible overlay for the same source and locale.
1136
+
1137
+ An overlay may replace only `title`, `description`, and body. It MUST preserve `type`,
1138
+ paths, ids, enums, status, permissions, portability, relations, and every other
1139
+ symbolic field from the source. Stale hashes, duplicate overlays, traversal, symlink
1140
+ targets, recursive translations, and translations of non-structural sources MUST
1141
+ fail closed.
1142
+
1143
+ A materialized locale is a disposable projection, not a translated vault. It MUST be
1144
+ written outside the source vault to a new or empty non-symlinked directory, preserve
1145
+ source-relative paths, and include enough projection metadata to identify its locale
1146
+ and source hashes. It may be deleted and rebuilt at any time.
1147
+
1050
1148
  ---
1051
1149
 
1052
1150
  ## 12. Conformance
@@ -1061,6 +1159,11 @@ Fixtures are distributed as a JSON document carrying:
1061
1159
  - `idempotency` — TTL and replay behavior.
1062
1160
  - `validation_rules` — envelope and content rules.
1063
1161
  - `runtime_contract` — trigger vocabulary and daemon idempotency rules (§11.8).
1162
+ - registry-extension checks — schema shape, regex validity, symlink rejection, and
1163
+ core/sibling collision rejection.
1164
+ - semantic/localization checks — deterministic indexing, privacy defaults, graph
1165
+ edges, exact source hashes, immutable overlay identity, and safe materialization
1166
+ (§11.9).
1064
1167
  - `fixtures[]` — each with a `request`, an `expected_response`, and an
1065
1168
  OPTIONAL `expected_http_status`.
1066
1169
  - `error_codes` — the canonical code table.
@@ -1068,7 +1171,8 @@ Fixtures are distributed as a JSON document carrying:
1068
1171
  The conformance fixture set is the shared test contract between all SSSS
1069
1172
  implementations. A host MUST NOT claim SSSS conformance without passing the current
1070
1173
  fixture set. Hosts implementing workflow daemons SHOULD also run the reference
1071
- runtime checks exposed by `@ssss/cli/runtime`.
1174
+ runtime checks exposed by `@gregiteen/ssss-cli/runtime`. Hosts exposing semantic
1175
+ search or localized projections MUST also pass the §11.9 checks.
1072
1176
 
1073
1177
  ---
1074
1178
 
@@ -1096,7 +1200,7 @@ opaque ID as the slug and keep the human-readable label in `title` / `name`.
1096
1200
  This document is versioned independently of any host and of the conformance
1097
1201
  fixture set.
1098
1202
 
1099
- - The spec version is stated in the document header (currently **v0.6 — Draft**).
1203
+ - The spec version is stated in the document header (currently **v0.7 — Draft**).
1100
1204
  - Breaking changes to the file format, the type registry, or the Operation
1101
1205
  Contract increment the spec version.
1102
1206
  - Until **v1.0**, any version MAY introduce breaking changes.
@@ -1208,7 +1312,7 @@ them without a spec change.
1208
1312
  serialization of `files` (path-sorted, §16.1). An importer MUST recompute it and reject
1209
1313
  a bundle whose files do not match. This is what makes a bundle tamper-evident and what a
1210
1314
  marketplace lists against.
1211
- - `exporter` — an identifier for the tool/host that produced the bundle (`"@ssss/cli@0.3.0"`).
1315
+ - `exporter` — an identifier for the tool/host that produced the bundle (`"@gregiteen/ssss-cli@0.8.0"`).
1212
1316
  - `signature` — OPTIONAL detached signature over `content_hash` for a sold bundle, so a
1213
1317
  buyer can verify authorship. Unsigned bundles are valid; signing is a marketplace concern.
1214
1318
 
@@ -1313,7 +1417,8 @@ cannot resolve a link MUST fail the provision rather than emit a dangling refere
1313
1417
 
1314
1418
  The following frontmatter keys are reserved by this spec across all primitives and
1315
1419
  MUST NOT be repurposed by hosts: `type`, `slug`, `schema_version`, `status`,
1316
- `feedback`, `confidence`.
1420
+ `feedback`, `confidence`, `semantic_id`, `relations`, `locale`, `translation_id`,
1421
+ `source_path`, `source_hash`, and `translated_fields`.
1317
1422
 
1318
1423
  Hosts adding their own frontmatter fields SHOULD prefix them `x_` to remain
1319
1424
  forward-compatible with future spec revisions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gregiteen/ssss-cli",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "CLI tools and the reference engine for the Structured Semantic Syntax System",
5
5
  "main": "src/engine.mjs",
6
6
  "exports": {
@@ -10,13 +10,14 @@
10
10
  "./registry": "./src/registry.mjs",
11
11
  "./frontmatter": "./src/frontmatter.mjs",
12
12
  "./bundle": "./src/bundle.mjs",
13
+ "./semantic": "./src/semantic.mjs",
13
14
  "./conformance/fixtures.json": "./conformance/fixtures.json",
14
15
  "./conformance/reference-bundle.ucw.json": "./conformance/reference-bundle.ucw.json",
15
16
  "./registry/core.json": "./registry/core.json",
16
17
  "./package.json": "./package.json"
17
18
  },
18
19
  "bin": {
19
- "ssss": "./scripts/ssss.mjs"
20
+ "ssss": "scripts/ssss.mjs"
20
21
  },
21
22
  "type": "module",
22
23
  "engines": {
@@ -29,6 +30,7 @@
29
30
  "conformance",
30
31
  "docs/ssss-spec.md",
31
32
  "docs/help",
33
+ "skills/ssss",
32
34
  "VERSION",
33
35
  "README.md",
34
36
  "CHANGELOG.md",
@@ -46,7 +48,10 @@
46
48
  "vault",
47
49
  "operation-contract",
48
50
  "ucw",
49
- "provisioning"
51
+ "provisioning",
52
+ "semantic-search",
53
+ "localization",
54
+ "translation"
50
55
  ],
51
56
  "author": "Greg Iteen",
52
57
  "license": "ISC",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "https://ssss.dev/registry/v1",
3
3
  "registry": "core",
4
- "spec_version": "0.6",
5
- "description": "The canonical SSSS core primitive registry. These 14 document primitives and 5 contract primitives are defined by the SSSS specification (docs/ssss-spec.md §5) and are owned by this standard. Every document primitive declares a portability class (§5.5); the registry also defines the workflow runtime contract (§11.8), the `.ucw` bundle format (§16), and the provisioning contract (§17). A conformant host MUST implement any core primitive it uses according to this registry. Applications extend the core with their own primitives via an extension registry (see registry/README.md); extensions MUST NOT redefine a core type.",
4
+ "spec_version": "0.7",
5
+ "description": "The canonical SSSS core primitive registry. These 15 document primitives and 5 contract primitives are defined by the SSSS specification (docs/ssss-spec.md §5) and are owned by this standard. Every document primitive declares a portability class (§5.5); the registry also defines the workflow runtime contract (§11.8), semantic/localization contract (§11.9), `.ucw` bundle format (§16), and provisioning contract (§17). A conformant host MUST implement any core primitive it uses according to this registry. Applications extend the core with their own primitives via an extension registry; extensions MUST NOT redefine a core or sibling-extension type.",
6
6
  "conformance": "A host is core-conformant for a primitive if a file of that type validates exactly when all required_fields are present and non-empty, and (for append_only types) writes only append.",
7
7
 
8
8
  "document_primitives": {
@@ -136,6 +136,34 @@
136
136
  "portability": "structural",
137
137
  "required_fields": ["type", "release_id", "version", "schema_version", "summary", "released_at"],
138
138
  "spec_ref": "§5.4 release"
139
+ },
140
+ "translation": {
141
+ "family": "localization",
142
+ "canonical_path": "translations/<locale>/<source-path>.md",
143
+ "append_only": false,
144
+ "portability": "structural",
145
+ "required_fields": ["type", "translation_id", "source_path", "source_hash", "locale", "status", "translated_fields"],
146
+ "optional_fields": ["translated_title", "translated_description", "translator", "reviewed_at"],
147
+ "immutable_fields": ["translation_id", "source_path", "locale"],
148
+ "enums": {
149
+ "status": ["draft", "reviewed", "approved"],
150
+ "translated_fields": ["title", "description", "body"]
151
+ },
152
+ "patterns": {
153
+ "translation_id": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$",
154
+ "locale": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
155
+ "source_hash": "^sha256:[a-f0-9]{64}$"
156
+ },
157
+ "references": {
158
+ "source_path": {
159
+ "must_exist": true,
160
+ "disallowed_types": ["translation"],
161
+ "allowed_portability": ["structural"],
162
+ "hash_field": "source_hash"
163
+ }
164
+ },
165
+ "notes": "A non-destructive presentation overlay. Only title, description, and body may be translated; symbolic control fields remain byte-for-byte sourced from the referenced structural document.",
166
+ "spec_ref": "§5.4 translation"
139
167
  }
140
168
  },
141
169
 
@@ -150,6 +178,7 @@
150
178
  "universal_frontmatter": {
151
179
  "required": ["type", "title", "description", "timestamp"],
152
180
  "recommended_okf": ["resource", "tags", "aliases"],
181
+ "recommended_semantic": ["semantic_id", "resource", "tags", "aliases", "relations", "locale"],
153
182
  "spec_ref": "§4.2"
154
183
  },
155
184
 
@@ -219,7 +248,18 @@
219
248
  "spec_ref": "§11.8"
220
249
  },
221
250
 
222
- "reserved_keys": ["type", "slug", "schema_version", "status", "feedback", "confidence"],
251
+ "semantic": {
252
+ "version": 1,
253
+ "identity_fields": ["semantic_id", "resource", "type", "path"],
254
+ "surface_fields": ["title", "description", "name", "slug", "aliases", "tags"],
255
+ "relation_fields": ["relations", "wiki_links", "markdown_links"],
256
+ "translatable_fields": ["title", "description", "body"],
257
+ "locale_pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
258
+ "safe_default": "Semantic indexes exclude tenant_private and resource_bound documents unless include_private is explicitly enabled. Translation overlays may reference structural sources only.",
259
+ "spec_ref": "§11.9"
260
+ },
261
+
262
+ "reserved_keys": ["type", "slug", "schema_version", "status", "feedback", "confidence", "semantic_id", "locale", "translation_of", "translation_source_hash"],
223
263
  "host_field_prefix": "x_",
224
264
  "spec_ref_reserved": "Appendix A"
225
265
  }
@@ -37,7 +37,15 @@ const ENGINE_FILES = [
37
37
  // spec §6.3 + §9). If a primitive declares one, the engine source MUST
38
38
  // reference it — otherwise the registry is making a promise the engine
39
39
  // doesn't keep.
40
- const ENGINE_ENFORCED_KEYS = ['required_fields', 'required_when', 'enums', 'append_only'];
40
+ const ENGINE_ENFORCED_KEYS = [
41
+ 'required_fields',
42
+ 'required_when',
43
+ 'enums',
44
+ 'patterns',
45
+ 'immutable_fields',
46
+ 'references',
47
+ 'append_only',
48
+ ];
41
49
 
42
50
  // Keys that are real and load-bearing but are intentionally consumed
43
51
  // elsewhere (export/bundle time, documentation, or the registry loader
@@ -75,6 +83,7 @@ function engineReferencesKey(engineSources, key) {
75
83
  const patterns = [
76
84
  new RegExp(`\\bdef\\.${key}\\b`),
77
85
  new RegExp(`\\btypeDef\\.${key}\\b`),
86
+ new RegExp(`(?:\\.|\\?\\.)${key}\\b`),
78
87
  new RegExp(`\\['${key}'\\]`),
79
88
  new RegExp(`\\["${key}"\\]`),
80
89
  ];
@@ -15,10 +15,14 @@ import os from 'node:os';
15
15
  import path from 'node:path';
16
16
  import { fileURLToPath } from 'node:url';
17
17
  import { exportBundle, validateBundle } from '../src/bundle.mjs';
18
+ import { documentHash } from '../src/registry.mjs';
18
19
  import { generateIndexes } from './autolink.mjs';
19
20
 
20
21
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
22
  const OUT = path.resolve(__dirname, '..', 'conformance', 'reference-bundle.ucw.json');
23
+ const PACKAGE = JSON.parse(
24
+ fs.readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf8')
25
+ );
22
26
 
23
27
  // ─── The reference vault ────────────────────────────────────────────────────
24
28
  const VAULT = {
@@ -104,11 +108,30 @@ description: Private support task for an attendee seat-change request.
104
108
  timestamp: 2026-07-02T00:00:00Z
105
109
  priority: high
106
110
  category: support
107
- status: open
111
+ status: pending
108
112
  ---
109
113
  Attendee jane@example.com requested a seat change.`,
110
114
  };
111
115
 
116
+ // Structural translation overlay — hash-bound to the exact source document and
117
+ // applied only by the semantic/localization projection (§11.9).
118
+ VAULT['translations/es/rules/refund-policy.md'] =
119
+ `---
120
+ type: translation
121
+ title: Spanish Refund Policy Translation
122
+ description: Approved Spanish presentation overlay for the festival refund policy.
123
+ timestamp: 2026-07-10T00:00:00Z
124
+ translation_id: refund-policy-es
125
+ source_path: rules/refund-policy.md
126
+ source_hash: ${documentHash(VAULT['rules/refund-policy.md'])}
127
+ locale: es
128
+ status: approved
129
+ translated_fields: [title, description, body]
130
+ translated_title: Política de reembolsos
131
+ translated_description: Explica cuándo están disponibles los reembolsos para asistentes.
132
+ ---
133
+ Los reembolsos están disponibles hasta catorce días antes del evento.`;
134
+
112
135
  function buildVault() {
113
136
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ssss-refvault-'));
114
137
  const files = [];
@@ -134,7 +157,7 @@ try {
134
157
  name: 'Festival in a Box',
135
158
  description: 'A complete music-festival operation as a tradeable SSSS bundle.',
136
159
  version: '1.0.0',
137
- exporter: '@ssss/cli@0.7.0',
160
+ exporter: `${PACKAGE.name}@${PACKAGE.version}`,
138
161
  requiredExtensions: ['festech'],
139
162
  parameters: [
140
163
  { key: 'business_name', label: 'Festival name', type: 'string', scope: 'workspace', source: 'user', required: true },
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import fs from 'node:fs';
9
9
  import path from 'node:path';
10
- import { exportBundle } from '../src/bundle.mjs';
10
+ import { DEFAULT_EXPORTER, exportBundle } from '../src/bundle.mjs';
11
11
  import { parseArgs, usage, die, wantsHelp } from './lib/cli.mjs';
12
12
 
13
13
  const HELP = usage({
@@ -19,7 +19,7 @@ const HELP = usage({
19
19
  ['--name <s>', 'Bundle display name.'],
20
20
  ['--description <s>', 'Bundle description.'],
21
21
  ['--bundle-version <s>', 'Bundle version string (default: 0.1.0).'],
22
- ['--exporter <s>', 'Exporter id recorded in provenance (default: @ssss/cli).'],
22
+ ['--exporter <s>', `Exporter id recorded in provenance (default: ${DEFAULT_EXPORTER}).`],
23
23
  ['--ext <name>', 'Declare a required extension registry (repeatable).'],
24
24
  ['--exported-at <iso>', 'Override the export timestamp (default: epoch, for determinism).'],
25
25
  ['--registry <dir>', 'Registry directory (default: the package core registry).'],
@@ -50,7 +50,7 @@ export async function run(argv) {
50
50
  name: flags.name || path.basename(path.resolve(vault)),
51
51
  description: flags.description || '',
52
52
  version: flags['bundle-version'] || '0.1.0',
53
- exporter: flags.exporter || '@ssss/cli',
53
+ exporter: flags.exporter || DEFAULT_EXPORTER,
54
54
  requiredExtensions: flags.ext || [],
55
55
  ...(flags['exported-at'] ? { exportedAt: flags['exported-at'] } : {}),
56
56
  });
@@ -63,7 +63,11 @@ export async function run(argv) {
63
63
  const engine = createEngine({ registryDir: flags.registry });
64
64
  const result = importBundle(envelopes, vault, engine);
65
65
  const failed = result.results.filter((r) => !r.success);
66
- console.log(`${result.ok ? '✓' : '✗'} import — ${result.committed} committed, ${envelopes.length - result.committed} unchanged (idempotent), ${failed.length} failed → ${vault}`);
66
+ if (flags['dry-run']) {
67
+ console.log(`${result.ok ? '✓' : '✗'} import dry-run — ${result.wouldCommit || 0} would commit, ${envelopes.length - (result.wouldCommit || 0)} unchanged (idempotent), ${failed.length} failed → ${vault}`);
68
+ } else {
69
+ console.log(`${result.ok ? '✓' : '✗'} import — ${result.committed} committed, ${envelopes.length - result.committed} unchanged (idempotent), ${failed.length} failed → ${vault}`);
70
+ }
67
71
  if (failed.length) {
68
72
  for (const r of failed) console.error(` ✗ ${r.path}: ${(r.validation?.errors || []).join('; ')}`);
69
73
  process.exit(1);
@@ -0,0 +1,44 @@
1
+ /** `ssss localize` — materialize a non-destructive locale projection. */
2
+ import path from 'node:path';
3
+ import { materializeLocale } from '../src/semantic.mjs';
4
+ import { parseArgs, usage, die, wantsHelp } from './lib/cli.mjs';
5
+
6
+ const HELP = usage({
7
+ summary: 'Materialize approved translation overlays as a derived vault projection (spec §11.9).',
8
+ usage: 'ssss localize <vault-dir> --locale <tag> --out <empty-dir> [options]',
9
+ options: [
10
+ ['--locale <tag>', 'Required BCP47-style target locale.'],
11
+ ['--out <dir>', 'Required empty directory outside the source vault.'],
12
+ ['--include-private', 'Explicitly include private/resource-bound source documents.'],
13
+ ['--include-drafts', 'Allow non-approved translation overlays.'],
14
+ ['--registry <dir>', 'Registry directory (default: package registry).'],
15
+ ],
16
+ examples: [
17
+ 'ssss localize ./vault --locale es --out ./derived/es',
18
+ ],
19
+ seeAlso: ['ssss semantic', 'ssss help localization'],
20
+ });
21
+
22
+ export async function run(argv) {
23
+ if (wantsHelp(argv)) { console.log(HELP); return; }
24
+ const { positionals, flags } = parseArgs(argv, {
25
+ booleans: ['include-private', 'include-drafts'],
26
+ });
27
+ const vault = positionals[0];
28
+ if (!vault || !flags.locale || !flags.out) die('localize requires a vault, --locale, and --out.\n\n' + HELP);
29
+ try {
30
+ const manifest = materializeLocale(
31
+ path.resolve(vault),
32
+ flags.locale,
33
+ path.resolve(flags.out),
34
+ {
35
+ includePrivate: !!flags['include-private'],
36
+ includeDrafts: !!flags['include-drafts'],
37
+ registryDir: flags.registry,
38
+ }
39
+ );
40
+ process.stdout.write(JSON.stringify(manifest, null, 2) + '\n');
41
+ } catch (error) {
42
+ die(error.message);
43
+ }
44
+ }
@@ -2,7 +2,7 @@
2
2
  * `ssss new` — scaffold a fresh repo wired for SSSS (and, optionally, Total Recall).
3
3
  *
4
4
  * Produces a ready-to-run project: a starter `vault/` of core primitives, the
5
- * `@ssss/cli` dependency pinned to this CLI's own version tag, a dependency-free
5
+ * `@gregiteen/ssss-cli` dependency pinned to this CLI's own version tag, a dependency-free
6
6
  * conformance test (`node --test`) that replays the canonical fixtures through the
7
7
  * engine AND round-trips the vault as a `sale` bundle, plus a CLAUDE.md describing
8
8
  * the conventions. With `--with-total-recall` it also wires the Total Recall
@@ -31,7 +31,7 @@ const HELP = usage({
31
31
  ['--with-total-recall', 'Also wire the Total Recall memory OS (total-recall-brain).'],
32
32
  ['--install', 'Run `npm install` after scaffolding (and Total Recall init if requested).'],
33
33
  ['--no-git', 'Do not run `git init`.'],
34
- ['--ref <git-ref>', `Pin @ssss/cli to this ref (default: v${VERSION}).`],
34
+ ['--ref <git-ref>', `Pin @gregiteen/ssss-cli to this ref (default: v${VERSION}).`],
35
35
  ['--force', 'Allow scaffolding into a non-empty directory.'],
36
36
  ],
37
37
  examples: [
@@ -81,7 +81,7 @@ export async function run(argv) {
81
81
  export: 'ssss export vault --profile sale --out dist/bundle.ucw.json',
82
82
  validate: 'ssss conformance --engine',
83
83
  },
84
- dependencies: { '@ssss/cli': `github:gregiteen/ssss#${ref}` },
84
+ dependencies: { '@gregiteen/ssss-cli': `github:gregiteen/ssss#${ref}` },
85
85
  ...(withTR ? { devDependencies: { 'total-recall-brain': 'latest' } } : {}),
86
86
  };
87
87
  W(root, 'package.json', JSON.stringify(pkg, null, 2) + '\n');
@@ -94,7 +94,7 @@ export async function run(argv) {
94
94
  W(root, 'vault/assistants/concierge.md',
95
95
  '---\ntype: assistant\ntitle: Concierge\ndescription: Starter assistant definition for the project.\ntimestamp: 2026-07-02T00:00:00Z\nname: Concierge\n---\n\n# Concierge\n\nA starter assistant definition.\n');
96
96
  W(root, 'vault/tasks/first-task.md',
97
- '---\ntype: task\ntitle: First Task\ndescription: Starter private setup task that demonstrates tenant_private filtering.\ntimestamp: 2026-07-02T00:00:00Z\npriority: normal\ncategory: setup\nstatus: open\n---\n\n# First task\n\nThis is `tenant_private` (§5.5) — it is **dropped** from `template`/`sale` exports.\n');
97
+ '---\ntype: task\ntitle: First Task\ndescription: Starter private setup task that demonstrates tenant_private filtering.\ntimestamp: 2026-07-02T00:00:00Z\npriority: normal\ncategory: setup\nstatus: pending\n---\n\n# First task\n\nThis is `tenant_private` (§5.5) — it is **dropped** from `template`/`sale` exports.\n');
98
98
 
99
99
  // ── conformance test (zero-dependency: node --test) ─────────────────────
100
100
  W(root, 'test/ssss-conformance.test.mjs', CONFORMANCE_TEST);
@@ -107,7 +107,7 @@ export async function run(argv) {
107
107
  // ── git + install (best-effort, flag-gated, no shell) ───────────────────
108
108
  const log = (m) => console.error(m);
109
109
  log(`Scaffolded SSSS project → ${root}`);
110
- log(` @ssss/cli pinned to github:gregiteen/ssss#${ref}`);
110
+ log(` @gregiteen/ssss-cli pinned to github:gregiteen/ssss#${ref}`);
111
111
  if (withTR) log(' Total Recall wired (total-recall-brain).');
112
112
 
113
113
  if (!flags['no-git'] && !fs.existsSync(path.join(root, '.git'))) {
@@ -153,11 +153,11 @@ import fs from 'node:fs';
153
153
  import os from 'node:os';
154
154
  import path from 'node:path';
155
155
  import { fileURLToPath } from 'node:url';
156
- import { createEngine } from '@ssss/cli/engine';
157
- import { exportBundle, validateBundle, provisionBundle, importBundle } from '@ssss/cli/bundle';
156
+ import { createEngine } from '@gregiteen/ssss-cli/engine';
157
+ import { exportBundle, validateBundle, provisionBundle, importBundle } from '@gregiteen/ssss-cli/bundle';
158
158
 
159
159
  const require = createRequire(import.meta.url);
160
- const { fixtures } = require('@ssss/cli/conformance/fixtures.json');
160
+ const { fixtures } = require('@gregiteen/ssss-cli/conformance/fixtures.json');
161
161
  const VAULT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'vault');
162
162
 
163
163
  test('engine implements the canonical Operation Contract (spec §6)', () => {
@@ -199,7 +199,7 @@ function readme(name, withTR) {
199
199
  return `# ${name}
200
200
 
201
201
  An [SSSS](https://github.com/gregiteen/ssss)-native project: a Markdown **vault** is
202
- the source of truth, validated and packaged by the dependency-free \`@ssss/cli\`.
202
+ the source of truth, validated and packaged by the dependency-free \`@gregiteen/ssss-cli\`.
203
203
 
204
204
  ## Layout
205
205
 
@@ -240,9 +240,9 @@ This repo uses **SSSS** (Structured Semantic Syntax System) as its state contrac
240
240
 
241
241
  ## Source of truth
242
242
  - \`vault/\` is the only source of truth — typed Markdown documents with YAML
243
- frontmatter. Every file declares a \`type\` defined in the \`@ssss/cli\` core registry.
243
+ frontmatter. Every file declares a \`type\` defined in the \`@gregiteen/ssss-cli\` core registry.
244
244
  - Mutate the vault through the standard, not by hand-writing files in bulk:
245
- \`npx ssss\` for bundle/tenant tooling, or the \`@ssss/cli/engine\` Operation Contract
245
+ \`npx ssss\` for bundle/tenant tooling, or the \`@gregiteen/ssss-cli/engine\` Operation Contract
246
246
  in code.
247
247
 
248
248
  ## Portability (§5.5) — the rule that matters