@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.
- package/CHANGELOG.md +63 -4
- package/README.md +29 -13
- package/VERSION +1 -1
- package/conformance/README.md +17 -11
- package/conformance/fixtures.json +68 -2
- package/conformance/reference-bundle.ucw.json +39 -5
- package/docs/help/bundle.md +6 -2
- package/docs/help/import.md +6 -2
- package/docs/help/leases.md +31 -0
- package/docs/help/localization.md +43 -0
- package/docs/help/overview.md +9 -5
- package/docs/help/portability.md +11 -3
- package/docs/help/runtime.md +3 -3
- package/docs/help/scaffold.md +2 -2
- package/docs/help/semantic.md +37 -0
- package/docs/ssss-spec.md +112 -7
- package/package.json +8 -3
- package/registry/core.json +43 -3
- package/scripts/audit-registry-field-usage.mjs +10 -1
- package/scripts/build-reference-bundle.mjs +25 -2
- package/scripts/cmd-export.mjs +3 -3
- package/scripts/cmd-import.mjs +5 -1
- package/scripts/cmd-localize.mjs +44 -0
- package/scripts/cmd-new.mjs +11 -11
- package/scripts/cmd-semantic.mjs +88 -0
- package/scripts/conformance.mjs +574 -2
- package/scripts/ssss.mjs +6 -2
- package/skills/ssss/SKILL.md +225 -0
- package/skills/ssss/evals/evals.json +37 -0
- package/skills/ssss/references/contract-reference.md +96 -0
- package/skills/ssss/scripts/validate-schema.mjs +258 -0
- package/skills/ssss/subagents/audit-ssss-contract.md +22 -0
- package/src/bundle.mjs +266 -41
- package/src/engine.mjs +78 -4
- package/src/frontmatter.mjs +141 -38
- package/src/registry.mjs +249 -7
- package/src/semantic.mjs +402 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** `ssss semantic` — build/query a deterministic, privacy-safe semantic projection. */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import { buildSemanticIndex, searchSemanticIndex } from '../src/semantic.mjs';
|
|
6
|
+
import { parseArgs, usage, die, wantsHelp } from './lib/cli.mjs';
|
|
7
|
+
|
|
8
|
+
const HELP = usage({
|
|
9
|
+
summary: 'Build or query the deterministic SSSS semantic index (spec §11.9).',
|
|
10
|
+
usage: 'ssss semantic <vault-dir> [options]',
|
|
11
|
+
options: [
|
|
12
|
+
['--query <text>', 'Return ranked matches instead of the entire index.'],
|
|
13
|
+
['--locale <tag>', 'Apply approved translation overlays for this locale.'],
|
|
14
|
+
['--type <name>', 'Restrict query results to a primitive type (repeatable).'],
|
|
15
|
+
['--limit <n>', 'Maximum query results (default: 10).'],
|
|
16
|
+
['--include-private', 'Explicitly include tenant_private/resource_bound documents.'],
|
|
17
|
+
['--include-drafts', 'Allow non-approved translation overlays.'],
|
|
18
|
+
['--registry <dir>', 'Registry directory (default: package registry).'],
|
|
19
|
+
['--out <file>', 'Write JSON outside the vault instead of stdout.'],
|
|
20
|
+
],
|
|
21
|
+
examples: [
|
|
22
|
+
'ssss semantic ./vault --query "refund policy"',
|
|
23
|
+
'ssss semantic ./vault --locale es --out ./derived/semantic-es.json',
|
|
24
|
+
],
|
|
25
|
+
seeAlso: ['ssss localize', 'ssss help semantic', 'ssss help localization'],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function physicalTarget(value) {
|
|
29
|
+
const requested = path.resolve(value);
|
|
30
|
+
let cursor = requested;
|
|
31
|
+
const suffix = [];
|
|
32
|
+
while (!fs.existsSync(cursor)) {
|
|
33
|
+
suffix.unshift(path.basename(cursor));
|
|
34
|
+
cursor = path.dirname(cursor);
|
|
35
|
+
}
|
|
36
|
+
return path.join(fs.realpathSync(cursor), ...suffix);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function writeOutsideVault(vault, output, content) {
|
|
40
|
+
const source = fs.realpathSync(path.resolve(vault));
|
|
41
|
+
const target = physicalTarget(output);
|
|
42
|
+
if (target === source || target.startsWith(source + path.sep)) {
|
|
43
|
+
throw new Error('Semantic projections must be written outside the source vault.');
|
|
44
|
+
}
|
|
45
|
+
if (fs.existsSync(target) && (fs.lstatSync(target).isSymbolicLink() || fs.statSync(target).isDirectory())) {
|
|
46
|
+
throw new Error(`Output must be a regular file: ${target}`);
|
|
47
|
+
}
|
|
48
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
49
|
+
const temporary = path.join(path.dirname(target), `.${path.basename(target)}.${crypto.randomUUID()}.tmp`);
|
|
50
|
+
fs.writeFileSync(temporary, content);
|
|
51
|
+
fs.renameSync(temporary, target);
|
|
52
|
+
return target;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function run(argv) {
|
|
56
|
+
if (wantsHelp(argv)) { console.log(HELP); return; }
|
|
57
|
+
const { positionals, flags } = parseArgs(argv, {
|
|
58
|
+
booleans: ['include-private', 'include-drafts'],
|
|
59
|
+
multi: ['type'],
|
|
60
|
+
});
|
|
61
|
+
const vault = positionals[0];
|
|
62
|
+
if (!vault) die('semantic needs a vault directory.\n\n' + HELP);
|
|
63
|
+
const limit = flags.limit === undefined ? 10 : Number(flags.limit);
|
|
64
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 1000) die('--limit must be an integer from 1 to 1000.');
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const index = buildSemanticIndex(path.resolve(vault), {
|
|
68
|
+
locale: flags.locale,
|
|
69
|
+
includePrivate: !!flags['include-private'],
|
|
70
|
+
includeDrafts: !!flags['include-drafts'],
|
|
71
|
+
registryDir: flags.registry,
|
|
72
|
+
});
|
|
73
|
+
const result = flags.query ? {
|
|
74
|
+
query: flags.query,
|
|
75
|
+
locale: index.locale,
|
|
76
|
+
include_private: index.include_private,
|
|
77
|
+
index_hash: index.index_hash,
|
|
78
|
+
results: searchSemanticIndex(index, flags.query, { types: flags.type, limit }),
|
|
79
|
+
} : index;
|
|
80
|
+
const json = JSON.stringify(result, null, 2) + '\n';
|
|
81
|
+
if (flags.out) {
|
|
82
|
+
const target = writeOutsideVault(vault, flags.out, json);
|
|
83
|
+
console.error(`Wrote semantic projection to ${target}`);
|
|
84
|
+
} else process.stdout.write(json);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
die(error.message);
|
|
87
|
+
}
|
|
88
|
+
}
|