@playola-radio/slipstream 0.1.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 (104) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +132 -0
  3. package/SKILL.md +63 -0
  4. package/THIRD-PARTY-NOTICES.md +36 -0
  5. package/contracts/interface/v2/schema.json +480 -0
  6. package/dist/answer-forwarder.js +58 -0
  7. package/dist/attribution-engine.js +164 -0
  8. package/dist/attribution-producer.js +153 -0
  9. package/dist/attribution-scoring.js +86 -0
  10. package/dist/attribution.js +120 -0
  11. package/dist/blob-source.js +100 -0
  12. package/dist/boundary-registry.js +47 -0
  13. package/dist/cas.js +99 -0
  14. package/dist/change-view.js +201 -0
  15. package/dist/claude-root-transcript.js +110 -0
  16. package/dist/cli.js +629 -0
  17. package/dist/clip-blob-reader.js +104 -0
  18. package/dist/clip-function-parser.js +83 -0
  19. package/dist/clip-language.js +15 -0
  20. package/dist/clip-projection-service.js +240 -0
  21. package/dist/clip-projection-worker.js +18 -0
  22. package/dist/clip-projection.js +585 -0
  23. package/dist/clip-worker-pool.js +118 -0
  24. package/dist/config.js +154 -0
  25. package/dist/control-client.js +98 -0
  26. package/dist/control-protocol.js +72 -0
  27. package/dist/daemon-location.js +33 -0
  28. package/dist/daemon.js +951 -0
  29. package/dist/display-fold.js +332 -0
  30. package/dist/engine.js +112 -0
  31. package/dist/entrypoint.js +17 -0
  32. package/dist/event.js +79 -0
  33. package/dist/evidence-ingest.js +60 -0
  34. package/dist/harness-context/claude.js +42 -0
  35. package/dist/harness-context/codex.js +49 -0
  36. package/dist/harness-context.js +49 -0
  37. package/dist/health.js +65 -0
  38. package/dist/http-reader.js +655 -0
  39. package/dist/http-security.js +50 -0
  40. package/dist/interface-projection.js +243 -0
  41. package/dist/interface-range-resolver.js +230 -0
  42. package/dist/interface-service.js +509 -0
  43. package/dist/interface-ts-pool.js +111 -0
  44. package/dist/interface-ts-worker.js +35 -0
  45. package/dist/interface-v2-comparison.js +135 -0
  46. package/dist/interface-v2-core.js +123 -0
  47. package/dist/interface-v2-typescript.js +448 -0
  48. package/dist/lock.js +197 -0
  49. package/dist/log-reader.js +148 -0
  50. package/dist/log.js +59 -0
  51. package/dist/maintenance.js +255 -0
  52. package/dist/mcp-forwarder.js +161 -0
  53. package/dist/mcp-protocol.js +92 -0
  54. package/dist/platform.js +21 -0
  55. package/dist/projection-admission.js +296 -0
  56. package/dist/projection-trace.js +17 -0
  57. package/dist/public-events.js +27 -0
  58. package/dist/question-hook.js +110 -0
  59. package/dist/questions.js +167 -0
  60. package/dist/reader-runtime.js +38 -0
  61. package/dist/reader.js +93 -0
  62. package/dist/recovery.js +303 -0
  63. package/dist/schema.js +108 -0
  64. package/dist/session.js +866 -0
  65. package/dist/sibling-module.js +10 -0
  66. package/dist/snapshot.js +15 -0
  67. package/dist/storage.js +111 -0
  68. package/dist/store-reader.js +185 -0
  69. package/dist/swift-grammar.js +268 -0
  70. package/dist/swift-interface-extract.js +344 -0
  71. package/dist/swift-interface.js +62 -0
  72. package/dist/swift-parse-host.js +174 -0
  73. package/dist/swift-parse-worker.js +34 -0
  74. package/dist/swift-parse.js +134 -0
  75. package/dist/swift-spans.js +62 -0
  76. package/dist/task-forwarder.js +152 -0
  77. package/dist/transcript/claude.js +199 -0
  78. package/dist/transcript/codex.js +132 -0
  79. package/dist/transcript/discovery.js +365 -0
  80. package/dist/transcript/file-reader.js +128 -0
  81. package/dist/transcript/fs-io.js +287 -0
  82. package/dist/transcript/runner.js +62 -0
  83. package/dist/transcript/steppers.js +30 -0
  84. package/dist/transcript/types.js +30 -0
  85. package/dist/transcript/watcher.js +133 -0
  86. package/dist/tui.js +168 -0
  87. package/package.json +60 -0
  88. package/schemas/projections/clip.v1.json +195 -0
  89. package/schemas/projections/clip.v2.json +212 -0
  90. package/schemas/projections/clip.v3.json +212 -0
  91. package/schemas/slipstream.capture.baseline.completed.v1.json +62 -0
  92. package/schemas/slipstream.capture.gap.v1.json +112 -0
  93. package/schemas/slipstream.change.attribution.v1.json +115 -0
  94. package/schemas/slipstream.enrichment.configured.v1.json +77 -0
  95. package/schemas/slipstream.enrichment.coverage.v1.json +95 -0
  96. package/schemas/slipstream.file.baselined.v1.json +122 -0
  97. package/schemas/slipstream.file.changed.v1.json +179 -0
  98. package/schemas/slipstream.harness.evidence.v1.json +145 -0
  99. package/schemas/slipstream.question.answered.v1.json +29 -0
  100. package/schemas/slipstream.question.dispatch_attempted.v1.json +28 -0
  101. package/schemas/slipstream.question.queued.v1.json +55 -0
  102. package/schemas/slipstream.session.resumed.v1.json +70 -0
  103. package/schemas/slipstream.session.started.v1.json +69 -0
  104. package/schemas/slipstream.task.started.v1.json +72 -0
package/dist/schema.js ADDED
@@ -0,0 +1,108 @@
1
+ import { readFile, readdir } from 'node:fs/promises';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { dirname, join } from 'node:path';
4
+ const SCHEMAS_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', 'schemas');
5
+ /** RFC3339 date-time with required timezone, matching CloudEvents `time`. */
6
+ const DATE_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
7
+ export async function loadSchema(type) {
8
+ const text = await readFile(join(SCHEMAS_DIR, `${type}.json`), 'utf8');
9
+ return JSON.parse(text);
10
+ }
11
+ export async function loadAllSchemas() {
12
+ const files = (await readdir(SCHEMAS_DIR)).filter((f) => f.endsWith('.json'));
13
+ const out = new Map();
14
+ for (const file of files) {
15
+ const text = await readFile(join(SCHEMAS_DIR, file), 'utf8');
16
+ out.set(file.replace(/\.json$/, ''), JSON.parse(text));
17
+ }
18
+ return out;
19
+ }
20
+ function typeMatches(schemaType, value) {
21
+ switch (schemaType) {
22
+ case 'object':
23
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
24
+ case 'array':
25
+ return Array.isArray(value);
26
+ case 'string':
27
+ return typeof value === 'string';
28
+ case 'boolean':
29
+ return typeof value === 'boolean';
30
+ case 'number':
31
+ return typeof value === 'number';
32
+ case 'integer':
33
+ return typeof value === 'number' && Number.isInteger(value);
34
+ default:
35
+ return true;
36
+ }
37
+ }
38
+ function resolveRef(ref, root) {
39
+ if (!ref.startsWith('#/'))
40
+ throw new Error(`unsupported $ref: ${ref}`);
41
+ let node = root;
42
+ for (const segment of ref.slice(2).split('/')) {
43
+ node = node[segment];
44
+ if (node === undefined)
45
+ throw new Error(`unresolved $ref: ${ref}`);
46
+ }
47
+ return node;
48
+ }
49
+ /** Returns an array of human-readable errors; empty means the value validates. */
50
+ export function validate(schema, value, root = schema, path = '$') {
51
+ const errors = [];
52
+ if (typeof schema.$ref === 'string') {
53
+ return validate(resolveRef(schema.$ref, root), value, root, path);
54
+ }
55
+ if ('const' in schema && value !== schema.const) {
56
+ errors.push(`${path}: expected const ${JSON.stringify(schema.const)}, got ${JSON.stringify(value)}`);
57
+ }
58
+ if (Array.isArray(schema.enum) && !schema.enum.some((e) => e === value)) {
59
+ errors.push(`${path}: ${JSON.stringify(value)} not in enum ${JSON.stringify(schema.enum)}`);
60
+ }
61
+ if (typeof schema.type === 'string' && !typeMatches(schema.type, value)) {
62
+ errors.push(`${path}: expected type ${schema.type}, got ${value === null ? 'null' : typeof value}`);
63
+ return errors; // further checks assume the type held
64
+ }
65
+ if (typeof schema.pattern === 'string' && typeof value === 'string') {
66
+ if (!new RegExp(schema.pattern).test(value)) {
67
+ errors.push(`${path}: ${JSON.stringify(value)} does not match /${schema.pattern}/`);
68
+ }
69
+ }
70
+ if (typeof value === 'string' && (typeof schema.minLength === 'number' || typeof schema.maxLength === 'number')) {
71
+ const length = [...value].length;
72
+ if (typeof schema.minLength === 'number' && length < schema.minLength)
73
+ errors.push(`${path}: length ${length} < minLength ${schema.minLength}`);
74
+ if (typeof schema.maxLength === 'number' && length > schema.maxLength)
75
+ errors.push(`${path}: length ${length} > maxLength ${schema.maxLength}`);
76
+ }
77
+ if (schema.format === 'date-time' && typeof value === 'string' && !DATE_TIME.test(value)) {
78
+ errors.push(`${path}: ${JSON.stringify(value)} is not an RFC3339 date-time`);
79
+ }
80
+ if (typeof schema.minimum === 'number' && typeof value === 'number' && value < schema.minimum) {
81
+ errors.push(`${path}: ${value} < minimum ${schema.minimum}`);
82
+ }
83
+ if (Array.isArray(schema.oneOf)) {
84
+ const matches = schema.oneOf.filter((sub) => validate(sub, value, root, path).length === 0);
85
+ if (matches.length !== 1) {
86
+ errors.push(`${path}: matched ${matches.length} of oneOf branches, expected exactly 1`);
87
+ }
88
+ }
89
+ if (schema.type === 'object' && typeof value === 'object' && value !== null) {
90
+ const obj = value;
91
+ if (Array.isArray(schema.required)) {
92
+ for (const key of schema.required) {
93
+ if (!(key in obj))
94
+ errors.push(`${path}: missing required property "${key}"`);
95
+ }
96
+ }
97
+ const props = (schema.properties ?? {});
98
+ for (const [key, sub] of Object.entries(props)) {
99
+ if (key in obj)
100
+ errors.push(...validate(sub, obj[key], root, `${path}.${key}`));
101
+ }
102
+ // additionalProperties intentionally unenforced — unknown fields are allowed.
103
+ }
104
+ if (schema.type === 'array' && Array.isArray(value) && schema.items) {
105
+ value.forEach((item, i) => errors.push(...validate(schema.items, item, root, `${path}[${i}]`)));
106
+ }
107
+ return errors;
108
+ }