@gregiteen/ssss-cli 0.9.0 → 0.9.1

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.
@@ -691,6 +691,53 @@ async function runCliSmokeConformance() {
691
691
  check('ssss import --dry-run reports would-commit counts and leaves target empty',
692
692
  dryRunOut.includes('would commit') && dryRunFiles.length === 0,
693
693
  dryRunOut.trim());
694
+
695
+ const primitiveOut = JSON.parse(execFileSync('node', [
696
+ path.join(__dirname, 'ssss.mjs'),
697
+ 'primitive', 'create',
698
+ '--namespace', 'acme',
699
+ '--name', '顧客予約',
700
+ '--language', 'ja',
701
+ '--fields', JSON.stringify([{ id: 'status', name: '状態', kind: 'enum', values: ['pending', 'confirmed'], required: true }]),
702
+ ], { encoding: 'utf8' }));
703
+ check('ssss primitive create emits a stable qualified identity',
704
+ /^acme:p_[a-f0-9]{20}$/.test(primitiveOut.primitive_id),
705
+ JSON.stringify(primitiveOut));
706
+
707
+ const defPath = path.join(tmp, 'definition.json');
708
+ fs.writeFileSync(defPath, `${JSON.stringify(primitiveOut)}\n`);
709
+ const inspectOut = JSON.parse(execFileSync('node', [
710
+ path.join(__dirname, 'ssss.mjs'),
711
+ 'primitive', 'inspect',
712
+ defPath,
713
+ ], { encoding: 'utf8' }));
714
+ const extensionPath = path.join(tmp, 'extension.json');
715
+ fs.writeFileSync(extensionPath, `${JSON.stringify(inspectOut.registry)}\n`);
716
+ const lockOut = JSON.parse(execFileSync('node', [
717
+ path.join(__dirname, 'ssss.mjs'),
718
+ 'registry', 'lock',
719
+ '--extension', extensionPath,
720
+ ], { encoding: 'utf8' }));
721
+ check('ssss registry lock emits integrity metadata',
722
+ typeof lockOut.integrity === 'string' && lockOut.integrity.startsWith('sha256:'),
723
+ JSON.stringify(lockOut));
724
+
725
+ const adapterOut = JSON.parse(execFileSync('node', [
726
+ path.join(__dirname, 'ssss.mjs'),
727
+ 'adapter', 'conformance',
728
+ ], { encoding: 'utf8' }));
729
+ check('ssss adapter conformance report is machine-readable and green',
730
+ adapterOut.passed === true && adapterOut.suites?.vfs_memory?.passed === true,
731
+ JSON.stringify(adapterOut));
732
+
733
+ const migrateOut = JSON.parse(execFileSync('node', [
734
+ path.join(__dirname, 'ssss.mjs'),
735
+ 'migrate', '0.8-to-0.9',
736
+ vault,
737
+ ], { encoding: 'utf8' }));
738
+ check('ssss migrate 0.8-to-0.9 dry-run emits backup manifest without writes',
739
+ migrateOut.dry_run === true && migrateOut.writes_performed === 0 && Array.isArray(migrateOut.backup_manifest),
740
+ JSON.stringify(migrateOut));
694
741
  } finally {
695
742
  fs.rmSync(tmp, { recursive: true, force: true });
696
743
  }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generate a minimal SPDX-lite SBOM for @gregiteen/ssss-cli publish artifacts.
4
+ * Dependency-free: packages only what is declared in package.json (zero runtime deps).
5
+ */
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import crypto from 'node:crypto';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
12
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
13
+
14
+ function walk(dir, out = []) {
15
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
16
+ if (entry.name === 'node_modules' || entry.name === '.git') continue;
17
+ const abs = path.join(dir, entry.name);
18
+ if (entry.isDirectory()) walk(abs, out);
19
+ else if (entry.isFile()) out.push(abs);
20
+ }
21
+ return out;
22
+ }
23
+
24
+ const files = walk(root).filter(
25
+ (f) =>
26
+ !f.includes(`${path.sep}artifacts${path.sep}`) &&
27
+ !f.endsWith('package-lock.json'),
28
+ );
29
+
30
+ const packages = [
31
+ {
32
+ name: pkg.name,
33
+ version: pkg.version,
34
+ downloadLocation: `https://registry.npmjs.org/${pkg.name}/-/${pkg.name.split('/').pop()}-${pkg.version}.tgz`,
35
+ filesAnalyzed: true,
36
+ licenseConcluded: pkg.license || 'NOASSERTION',
37
+ },
38
+ ];
39
+
40
+ // Zero runtime dependencies by design — still list optional peer/dev if present
41
+ for (const [section, deps] of Object.entries({
42
+ dependencies: pkg.dependencies || {},
43
+ optionalDependencies: pkg.optionalDependencies || {},
44
+ })) {
45
+ for (const [name, version] of Object.entries(deps)) {
46
+ packages.push({
47
+ name,
48
+ version: String(version).replace(/^[\^~]/, ''),
49
+ relationship: section,
50
+ });
51
+ }
52
+ }
53
+
54
+ const fileEntries = files.map((abs) => {
55
+ const rel = path.relative(root, abs).split(path.sep).join('/');
56
+ const buf = fs.readFileSync(abs);
57
+ return {
58
+ fileName: rel,
59
+ checksums: [
60
+ {
61
+ algorithm: 'SHA256',
62
+ checksumValue: crypto.createHash('sha256').update(buf).digest('hex'),
63
+ },
64
+ ],
65
+ };
66
+ });
67
+
68
+ const sbom = {
69
+ spdxVersion: 'SPDX-2.3',
70
+ dataLicense: 'CC0-1.0',
71
+ SPDXID: 'SPDXRef-DOCUMENT',
72
+ name: `${pkg.name}-${pkg.version}`,
73
+ documentNamespace: `https://github.com/gregiteen/ssss/sbom/${pkg.version}`,
74
+ creationInfo: {
75
+ created: new Date().toISOString(),
76
+ creators: ['Tool: ssss-generate-sbom'],
77
+ },
78
+ packages,
79
+ files: fileEntries,
80
+ relationships: [
81
+ {
82
+ spdxElementId: 'SPDXRef-DOCUMENT',
83
+ relationshipType: 'DESCRIBES',
84
+ relatedSpdxElement: 'SPDXRef-Package',
85
+ },
86
+ ],
87
+ comment:
88
+ 'SSSS reference package is intentionally dependency-free at runtime. Host apps supply adapters.',
89
+ };
90
+
91
+ const outDir = path.join(root, 'artifacts');
92
+ fs.mkdirSync(outDir, { recursive: true });
93
+ const outFile = path.join(outDir, `sbom-${pkg.version}.spdx.json`);
94
+ fs.writeFileSync(outFile, `${JSON.stringify(sbom, null, 2)}\n`);
95
+ console.log(`SBOM written: ${outFile}`);
96
+ console.log(`Packages: ${packages.length}, files hashed: ${fileEntries.length}`);
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Phase 9 — shared cross-host command corpus.
4
+ *
5
+ * Runs a normalized set of Operation Contract envelopes through the package
6
+ * kernel (MemoryVfs + memory durable stores) and prints a machine-readable
7
+ * report. Hosts can re-run the same envelopes via their bridges and compare
8
+ * success/valid/type verdicts against this reference.
9
+ */
10
+ import fs from 'node:fs';
11
+ import os from 'node:os';
12
+ import path from 'node:path';
13
+ import crypto from 'node:crypto';
14
+ import { fileURLToPath } from 'node:url';
15
+ import { createKernel, canonicalRequestHash } from '../src/kernel.mjs';
16
+ import { FileSystemVfs } from '../src/vfs.mjs';
17
+ import { MemoryEventStore } from '../src/events.mjs';
18
+ import { MemoryIdempotencyStore } from '../src/idempotency.mjs';
19
+ import { MemoryLeaseStore } from '../src/leases.mjs';
20
+ import { createValidator } from '../src/validator.mjs';
21
+ import { loadRegistries } from '../src/registry.mjs';
22
+
23
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
+
25
+ function ruleContent(name) {
26
+ return [
27
+ '---',
28
+ 'type: rule',
29
+ `title: ${name}`,
30
+ `description: Phase 9 corpus rule ${name}`,
31
+ 'timestamp: 2026-07-10T00:00:00Z',
32
+ `name: ${name}`,
33
+ '---',
34
+ '',
35
+ `Body for ${name}.`,
36
+ '',
37
+ ].join('\n');
38
+ }
39
+
40
+ function spanishRuleContent() {
41
+ return [
42
+ '---',
43
+ 'type: rule',
44
+ 'title: Bienvenida',
45
+ 'description: Regla estructural de corpus multilingüe',
46
+ 'timestamp: 2026-07-10T00:00:00Z',
47
+ 'name: bienvenida',
48
+ '---',
49
+ '',
50
+ 'Cuerpo en español.',
51
+ '',
52
+ ].join('\n');
53
+ }
54
+
55
+ const CORPUS = [
56
+ {
57
+ id: 'corpus-rule-create',
58
+ envelope: {
59
+ type: 'operation',
60
+ workspace_id: 'ws-corpus',
61
+ idempotency_key: 'corpus-rule-1',
62
+ path: 'rules/welcome.md',
63
+ content: ruleContent('welcome'),
64
+ },
65
+ expect: { success: true, valid: true },
66
+ },
67
+ {
68
+ id: 'corpus-rule-idempotent-replay',
69
+ envelope: {
70
+ type: 'operation',
71
+ workspace_id: 'ws-corpus',
72
+ idempotency_key: 'corpus-rule-1',
73
+ path: 'rules/welcome.md',
74
+ content: ruleContent('welcome'),
75
+ },
76
+ expect: { success: true, valid: true, replay: true },
77
+ },
78
+ {
79
+ id: 'corpus-rule-idempotent-conflict',
80
+ envelope: {
81
+ type: 'operation',
82
+ workspace_id: 'ws-corpus',
83
+ idempotency_key: 'corpus-rule-1',
84
+ path: 'rules/welcome.md',
85
+ content: ruleContent('welcome-changed'),
86
+ },
87
+ expect: { success: false },
88
+ },
89
+ {
90
+ id: 'corpus-dry-run',
91
+ envelope: {
92
+ type: 'operation',
93
+ workspace_id: 'ws-corpus',
94
+ idempotency_key: 'corpus-dry-1',
95
+ path: 'rules/dry.md',
96
+ content: ruleContent('dry'),
97
+ dry_run: true,
98
+ },
99
+ expect: { success: true, valid: true, dry_run: true },
100
+ },
101
+ {
102
+ id: 'corpus-multilingual-rule',
103
+ envelope: {
104
+ type: 'operation',
105
+ workspace_id: 'ws-corpus',
106
+ idempotency_key: 'corpus-es-1',
107
+ path: 'rules/bienvenida.md',
108
+ content: spanishRuleContent(),
109
+ },
110
+ expect: { success: true, valid: true },
111
+ },
112
+ {
113
+ id: 'corpus-missing-actor-denied',
114
+ envelope: {
115
+ type: 'operation',
116
+ workspace_id: 'ws-corpus',
117
+ idempotency_key: 'corpus-no-actor',
118
+ path: 'rules/no-actor.md',
119
+ content: ruleContent('no-actor'),
120
+ },
121
+ principal: null,
122
+ expect: { success: false },
123
+ },
124
+ ];
125
+
126
+ function principal() {
127
+ return {
128
+ id: 'phase9:corpus',
129
+ kind: 'system',
130
+ workspaceIds: ['ws-corpus'],
131
+ capabilities: ['*:*'],
132
+ authentication: { provider: 'phase9-corpus', assurance: 'system' },
133
+ };
134
+ }
135
+
136
+ async function main() {
137
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ssss-phase9-corpus-'));
138
+ const registrySet = loadRegistries();
139
+ const validator = createValidator({ registrySet });
140
+ const kernel = createKernel({
141
+ vfs: new FileSystemVfs(root),
142
+ eventStore: new MemoryEventStore(),
143
+ leaseStore: new MemoryLeaseStore(),
144
+ idempotencyStore: new MemoryIdempotencyStore(),
145
+ validator,
146
+ });
147
+
148
+ const results = [];
149
+ for (const caseDef of CORPUS) {
150
+ const p =
151
+ caseDef.principal === null
152
+ ? null
153
+ : caseDef.principal || principal();
154
+ let result;
155
+ try {
156
+ if (!p) {
157
+ // Simulate host fail-closed before kernel when identity missing
158
+ result = {
159
+ success: false,
160
+ validation: { valid: false, errors: ['Missing actor'] },
161
+ };
162
+ } else {
163
+ result = await kernel.execute(caseDef.envelope, { principal: p });
164
+ }
165
+ } catch (error) {
166
+ result = {
167
+ success: false,
168
+ validation: { valid: false, errors: [error.message] },
169
+ error: error.message,
170
+ };
171
+ }
172
+
173
+ const verdict = {
174
+ id: caseDef.id,
175
+ success: !!result.success,
176
+ valid: !!result.validation?.valid,
177
+ replay: !!result.replay,
178
+ dry_run: !!result.dry_run || !!caseDef.envelope.dry_run,
179
+ type: result.validation?.type || null,
180
+ errors: result.validation?.errors || [],
181
+ request_hash: canonicalRequestHash(caseDef.envelope),
182
+ };
183
+
184
+ const ok =
185
+ (caseDef.expect.success === undefined ||
186
+ verdict.success === caseDef.expect.success) &&
187
+ (caseDef.expect.valid === undefined ||
188
+ verdict.valid === caseDef.expect.valid) &&
189
+ (caseDef.expect.replay === undefined ||
190
+ verdict.replay === caseDef.expect.replay) &&
191
+ (caseDef.expect.dry_run === undefined ||
192
+ verdict.dry_run === caseDef.expect.dry_run);
193
+
194
+ results.push({ ...verdict, passed: ok });
195
+ console.log(`${ok ? '✅' : '❌'} ${caseDef.id} success=${verdict.success} valid=${verdict.valid}`);
196
+ }
197
+
198
+ const report = {
199
+ suite: 'phase9-cross-host-corpus',
200
+ package: '@gregiteen/ssss-cli',
201
+ version: JSON.parse(
202
+ fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'),
203
+ ).version,
204
+ generated_at: new Date().toISOString(),
205
+ passed: results.every((r) => r.passed),
206
+ results,
207
+ };
208
+
209
+ const outDir = path.join(__dirname, '../artifacts');
210
+ fs.mkdirSync(outDir, { recursive: true });
211
+ const outFile = path.join(outDir, 'phase9-cross-host-corpus.json');
212
+ fs.writeFileSync(outFile, `${JSON.stringify(report, null, 2)}\n`);
213
+ console.log(`\nReport: ${outFile}`);
214
+ console.log(`Overall: ${report.passed ? 'PASS' : 'FAIL'} (${results.filter((r) => r.passed).length}/${results.length})`);
215
+
216
+ fs.rmSync(root, { recursive: true, force: true });
217
+ process.exit(report.passed ? 0 : 1);
218
+ }
219
+
220
+ main().catch((error) => {
221
+ console.error(error);
222
+ process.exit(1);
223
+ });
@@ -1,221 +1,49 @@
1
1
  ---
2
2
  type: skill
3
- title: SSSS System Manager
3
+ title: SSSS Protocol Reference
4
4
  name: ssss
5
- description: "Inspect, validate, implement, or change SSSS primitives, registries, kernel commands, VFS/security adapters, events, projections, multilingual semantic runtime, generative UI, bundles, and host adapters. MANDATORY: Read this file before editing SSSS files or code."
6
- timestamp: 2026-07-10T00:00:00Z
5
+ description: "Use this skill when reading, writing, parsing, validating, or extending SSSS -- the Structured Semantic Syntax System: the SSSS Core Contract API, VFS-native primitives, operation/patch/event envelopes, leases, and projections. MANDATORY: You MUST read the full SKILL.md file before executing."
6
+ timestamp: 2026-07-15T00:00:00Z
7
7
  ---
8
8
 
9
- # SSSS — Structured Semantic Syntax System Manager
9
+ # SSSS — Structured Semantic Syntax System Reference
10
10
 
11
- SSSS is a vendor-neutral, Markdown-first state and mutation contract. Canonical
12
- state is typed Markdown plus append-only events. Databases, indexes, queues,
13
- dashboards, and search stores are host projections unless explicitly documented
14
- as external resources.
11
+ You are operating in a repository that implements, extends, or relies on the **Structured Semantic Syntax System (SSSS)**. SSSS is a database-free, Markdown-first schema and mutation contract for AI-agent state.
15
12
 
16
- ## Establish Ground Truth First
13
+ This skill provides the normative rules for interacting with an SSSS-compliant vault or host engine (like Total Recall).
17
14
 
18
- Do not infer the contract from an installed skill snapshot.
15
+ ## ⚠️ The VFS-First Mandate (Absolute Rule)
19
16
 
20
- 1. Find the repository root and inspect `package.json`, `VERSION`,
21
- `registry/core.json`, and `docs/ssss-spec.md` when they exist.
22
- 2. Treat `registry/core.json` as the machine-readable primitive contract and
23
- `docs/ssss-spec.md` as the normative explanation.
24
- 3. Treat `src/engine.mjs`, `src/runtime.mjs`, `src/semantic.mjs`,
25
- `src/bundle.mjs`, `src/registry.mjs`, and `src/frontmatter.mjs` as the
26
- reference behavior.
27
- 4. Treat host schemas and services as adapters or extension registries. Never
28
- promote host-only fields into the core standard without an explicit spec and
29
- registry change.
30
- 5. Read the current package name and version instead of hard-coding an alias.
31
- In this checkout the published package is `@gregiteen/ssss-cli`; the CLI is
32
- `ssss`.
17
+ **NEVER use raw database inserts, updates, or deletes to mutate application state in an SSSS environment!**
33
18
 
34
- If those files are absent, inspect the installed
35
- `@gregiteen/ssss-cli/registry/core.json` export. Use the bundled reference only
36
- as a fallback and report that the result is snapshot-based.
19
+ All persistent state (memories, agents, workflows, tasks) lives in the Virtual File System (VFS) as Markdown files with YAML frontmatter. The VFS is the absolute source of truth.
20
+ - If you are interacting via CLI: Use `npx total-recall remember` or `npx total-recall recall`.
21
+ - If you are building host code: You must route mutations through the SSSS **Operation Contract** engine (which handles idempotency, leasing, and semantic indexing), or use the provided API wrappers. Do not bypass the engine to write files directly.
37
22
 
38
- ## Authority Order
23
+ ## SSSS Core Concepts
39
24
 
40
- When sources disagree, resolve drift in this order:
25
+ ### 1. Primitives (The Data Model)
26
+ Data in SSSS is defined by standard primitives (e.g. `workflow`, `assistant`, `skill`, `memory`). Each primitive has a defined schema (in `registry/core.json` or extension registries) and belongs to a specific Portability Class:
27
+ - `structural`: Logic and system prompts (e.g. rules, workflows). Included in export templates.
28
+ - `tenant_private`: User data (e.g. chats, tasks). NEVER included in templates.
29
+ - `resource_bound`: Requires external setup (e.g. Twilio numbers). Exported only as a requirement.
41
30
 
42
- 1. Conformance fixtures and tests for observed executable behavior.
43
- 2. `registry/core.json` for required fields, enums, append behavior, and
44
- portability.
45
- 3. `docs/ssss-spec.md` for normative semantics.
46
- 4. Reference engine/runtime/bundle code.
47
- 5. Host extension registry and host adapter documentation.
48
- 6. Skills, examples, README prose, and copied mirrors.
31
+ ### 2. The Operation Contract (Envelopes)
32
+ When an SSSS engine processes a write, it receives an **Envelope**:
33
+ - `operation`: Creates or completely replaces a document.
34
+ - `patch`: Merges partial data into a document (e.g. updating task status).
35
+ - `event`: Appends an immutable log entry to a document.
36
+ - `delete`: Tombstones a replace-type document.
49
37
 
50
- Do not silently pick one side. Identify the mismatch, decide whether code or
51
- canon is wrong, update every affected source, and add a regression check.
38
+ ### 3. Idempotency and Leases
39
+ - **Idempotency**: All mutations must provide an `idempotency_key`. The engine ensures duplicate submissions do not result in duplicate state.
40
+ - **Leases**: Background tasks and workflows use the Lease store to acquire temporary locks on documents to prevent race conditions during execution.
52
41
 
53
- ## Document Contract
42
+ ### 4. Bundles (.ucw)
43
+ An SSSS vault can be packaged into a `.ucw` (Universal Containerized Workspace) bundle. A bundle is a portable snapshot containing a manifest, deterministic file paths, and content hashes for cryptographic integrity.
54
44
 
55
- Every SSSS document has YAML frontmatter and a Markdown body. SSSS-managed
56
- documents require the universal fields:
45
+ ## Validation
57
46
 
58
- - `type`
59
- - `title`
60
- - `description`
61
- - `timestamp`
62
-
63
- Primitive-specific required fields are additive. An SSSS-managed skill also
64
- requires `name`; a schema-v2 memory has knowledge-graph fields; a workflow
65
- requires `name`.
66
-
67
- Unknown frontmatter fields must be preserved for forward compatibility. Never
68
- drop a nested map, array, or unknown field during parse/serialize or patch.
69
-
70
- Registry declarations are executable contract. Enforce `required_fields`,
71
- `required_when`, `enums`, `patterns`, `immutable_fields`, `references`,
72
- `append_only`, and `portability`. Reject malformed extension definitions,
73
- symlinked registry files, and core or sibling type collisions during load.
74
-
75
- ## Mutation Contract
76
-
77
- Agent-generated mutations flow through the Operation Contract:
78
-
79
- ```text
80
- validate envelope
81
- -> verify safe workspace/idempotency/actor identifiers
82
- -> resolve and contain the target path
83
- -> replay or reject the idempotency key + request hash
84
- -> authorize with verified actor identity (fail closed)
85
- -> validate any active lease (fail closed)
86
- -> validate universal + primitive-specific content
87
- -> commit atomically
88
- -> append the audit event
89
- ```
90
-
91
- The mutation envelopes are:
92
-
93
- - `operation` — create or fully replace a replace-type document.
94
- - `patch` — merge an existing replace-type document without changing `type`.
95
- - `event` — append an immutable event record.
96
- - `delete` — remove a replace-type document and emit an audit event; reject
97
- append-type targets.
98
-
99
- Use `dry_run: true` for model-generated preflight. Idempotency is scoped by the
100
- effective request, not the key alone: the same request replays, while the same
101
- workspace/key with a different request hash is a conflict.
102
-
103
- ## Append, Lease, and Path Safety
104
-
105
- - `conversation` and `run` are append-only. Preserve prior bytes and append new
106
- records; never rewrite or delete them.
107
- - Events are immutable.
108
- - Paths must be relative, contained vault paths. Reject absolute paths,
109
- backslashes, null bytes, empty segments, `.`/`..`, directory targets, and
110
- symlink escapes.
111
- - Leases are actor-owned, operation-linked, expiring locks. Missing, mismatched,
112
- malformed, or unreadable lease state fails closed.
113
- - Hosts must overwrite caller-supplied actor data with verified session identity
114
- before authorization.
115
-
116
- ## Workflow Runtime
117
-
118
- Workflow frontmatter owns the schedule. Cron, daemon, webhook, file watcher, and
119
- event-loop processes are wake-up mechanisms, not a second scheduling database.
120
-
121
- Use `@gregiteen/ssss-cli/runtime` to deterministically derive the trigger event,
122
- task, and run envelopes. Duplicate ticks must replay idempotently. Queues and
123
- task dashboards are disposable projections over workflow state and events.
124
-
125
- ## Bundles and Portability
126
-
127
- Every document primitive resolves to one portability class:
128
-
129
- - `structural` — reusable model shipped in templates and sale bundles.
130
- - `tenant_private` — operator/customer runtime data; excluded from template and
131
- sale exports.
132
- - `resource_bound` — exported only as a requirement declaration; never leak the
133
- seller's bound resource value.
134
-
135
- Bundle paths must be unique, safe, and symlink-free. Validate content hashes,
136
- required extensions, primitive inventory, core version, parameters, and link
137
- integrity before import. Preflight the complete plan before the first commit so a
138
- late invalid envelope cannot leave a partial install. Provisioning produces
139
- deterministic Operation Contract envelopes; re-import must be a no-op.
140
-
141
- ## Multilingual Semantic Runtime
142
-
143
- Treat semantic indexes and rendered text/UI as disposable projections. Canonical
144
- documents are authored once in any language; do not create translation documents or
145
- localized canonical trees.
146
-
147
- - Index only `structural` documents by default. Include `tenant_private` and
148
- `resource_bound` sources only after an explicit authorized opt-in.
149
- - Derive stable identity from `semantic_id`, then `resource`, then source path.
150
- - Build edges from explicit `relations`, wiki links, and Markdown links.
151
- - Record embedding model identity and vector dimensions and report lexical and
152
- semantic evidence separately.
153
- - Render language at runtime through an injected adapter. Preserve primitive IDs,
154
- field IDs, enum codes, actions, permissions, paths, versions, hashes, and relations.
155
-
156
- ## Scope and Host Adapters
157
-
158
- The core standard does not collapse host ownership layers. A host may implement
159
- global/project or system/account/workspace overlays, but must document precedence
160
- and preserve isolation. Shared system skills should be inherited through an
161
- overlay rather than copied into every workspace.
162
-
163
- When working in Total Recall, use its validated-write and memory-validator
164
- adapter if those modules exist. In another host, locate its extension registry
165
- and conformance bridge. Do not quote Total Recall paths as universal SSSS
166
- architecture.
167
-
168
- ## Procedure for Changes
169
-
170
- 1. Classify the change: core primitive, contract behavior, runtime behavior,
171
- semantic/runtime-rendering behavior, bundle/provisioning behavior, projection, or
172
- host extension.
173
- 2. Inspect the registry, spec section, implementation, fixtures, and host bridge
174
- for that surface.
175
- 3. Make the smallest coherent change across code and canon.
176
- 4. Add positive, negative, replay, and invalid-path cases where applicable.
177
- 5. Run focused validation, then the full conformance gate.
178
- 6. Update skill/reference mirrors only after the executable contract is green.
179
-
180
- ## Validation
181
-
182
- Validate a Markdown document with the dependency-free skill helper:
183
-
184
- ```bash
185
- node skills/ssss/scripts/validate-schema.mjs path/to/document.md
186
- ```
187
-
188
- In the SSSS reference repository, the required gate is:
189
-
190
- ```bash
191
- npm test
192
- ```
193
-
194
- It covers registry/engine parity, shipped-skill conformance, Operation Contract
195
- fixtures, workflow runtime behavior, lease/frontmatter regressions,
196
- extension-registry hardening, multilingual semantic behavior,
197
- bundle/provisioning round trips, and CLI smoke tests.
198
-
199
- For host adapters, run the host's named SSSS conformance command as well. Do not
200
- substitute a loose YAML parse or a generic typecheck for the SSSS gate.
201
-
202
- ## Do Not
203
-
204
- - Do not treat an installed skill, copied spec, or README as newer than the live
205
- registry and conformance suite.
206
- - Do not use raw file writes for agent-generated vault mutations.
207
- - Do not make a derived database/index/queue the canonical record.
208
- - Do not add a primitive in prose without registry and fixture coverage.
209
- - Do not translate symbolic control fields or index private content by default.
210
- - Do not materialize a projection inside its source vault.
211
- - Do not mix document primitives with contract envelopes.
212
- - Do not claim conformance from HTTP success or file creation alone.
213
- - Do not publish package names, versions, or exporter identities without reading
214
- them from current package metadata.
215
-
216
- ## References
217
-
218
- Read `references/contract-reference.md` for the compact topology, primitive
219
- families, package entry points, and drift checklist. For normative detail, read
220
- the exact linked section of `docs/ssss-spec.md` rather than loading a stale
221
- vendored copy.
47
+ If you are writing tests or schemas in a host repository, ensure that:
48
+ 1. `MemoryNodeSchema` validations provide all required SSSS v2 properties (`status`, `created`, `updated`, `last_accessed`, `source`, `decay`).
49
+ 2. Schema changes maintain strict compatibility with the Open Knowledge Format (OKF) standard if applicable.
@@ -33,9 +33,10 @@ export function createCapabilityAuthorizer(options = {}) {
33
33
  if (principal.kind !== 'system' && !principal.workspaceIds.includes(workspaceId)) {
34
34
  return { allowed: false, reason: `Principal '${principal.id}' is not scoped to workspace '${workspaceId}'.` };
35
35
  }
36
+ const floorKey = definition?.qualified_type || definition?.primitive_id || definition?.type;
36
37
  const required = new Set([
37
38
  ...requiredCapabilities(definition, action),
38
- ...(policyFloors[definition?.qualified_type || definition?.type]?.[action] || []),
39
+ ...(policyFloors[floorKey]?.[action] || []),
39
40
  ...(context.policyFloor || []),
40
41
  ]);
41
42
  const granted = new Set(principal.capabilities || []);