@disclosureos/instruments 1.0.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 +37 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/constants/index.d.ts +7 -0
- package/dist/constants/index.js +111 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/factories/index.d.ts +15 -0
- package/dist/factories/index.js +28 -0
- package/dist/factories/index.js.map +1 -0
- package/dist/formatters/index.d.ts +11 -0
- package/dist/formatters/index.js +38 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/guards/index.d.ts +6 -0
- package/dist/guards/index.js +111 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +228 -0
- package/dist/index.js.map +1 -0
- package/dist/labels/index.d.ts +11 -0
- package/dist/labels/index.js +38 -0
- package/dist/labels/index.js.map +1 -0
- package/dist/manifest/index.d.ts +289 -0
- package/dist/manifest/index.js +104 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/validators/index.d.ts +17 -0
- package/dist/validators/index.js +138 -0
- package/dist/validators/index.js.map +1 -0
- package/package.json +103 -0
- package/schema/sensor-manifest.schema.json +473 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @disclosureos/instruments
|
|
2
|
+
|
|
3
|
+
All notable changes to `@disclosureos/instruments` are documented here. The format is
|
|
4
|
+
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## 1.0.0
|
|
8
|
+
|
|
9
|
+
### Major Changes
|
|
10
|
+
|
|
11
|
+
- b373962: Initial release: the **UAP Sensor Manifest** standard — the DisclosureOS
|
|
12
|
+
standard's first standalone document type besides `Observation`.
|
|
13
|
+
|
|
14
|
+
A `SensorManifest` catalogs one organization's detection hardware per sensor:
|
|
15
|
+
modality, records-enum mapping, timing provenance, measurements with GUM
|
|
16
|
+
uncertainty, raw-data locators, and calibration provenance under a
|
|
17
|
+
`none → candidate_identified → in_practice → documented` maturity gradient.
|
|
18
|
+
|
|
19
|
+
Ships the full DX quintet (labels, constants, guards, factories, formatters),
|
|
20
|
+
`validateSensorManifest` (schema + unique-id + unflagged-mapping invariants),
|
|
21
|
+
and a drift-tested JSON Schema artifact at
|
|
22
|
+
`https://os.disclosure.org/schema/instruments/1.0.0/sensor-manifest.json`.
|
|
23
|
+
|
|
24
|
+
Sensor readings in `@disclosureos/records` cite manifest entries through
|
|
25
|
+
`SensorReading.sensorRef` (`"<org-slug>:<sensor-id>"`), and
|
|
26
|
+
`@disclosureos/scoring` consumes manifests through the `calibrationTrust`
|
|
27
|
+
evaluator-weight hook.
|
|
28
|
+
|
|
29
|
+
Proposed by [ELDÆON](https://eldaeon.com/)
|
|
30
|
+
([#5](https://github.com/disclosurefoundation/disclosureos/pull/5)), the
|
|
31
|
+
standard's first external contribution, and promoted into the framework as a
|
|
32
|
+
foundation package.
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [e6ff99c]
|
|
37
|
+
- @disclosureos/records@1.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Disclosure Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# @disclosureos/instruments
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
|
|
5
|
+
The **UAP Sensor Manifest** — a per-sensor specification standard for detection
|
|
6
|
+
hardware in the [DisclosureOS](https://github.com/disclosurefoundation) ecosystem.
|
|
7
|
+
DisclosureOS records describe *what was observed*; a sensor manifest describes
|
|
8
|
+
*the hardware that produced the data*, so field missions and data drops from
|
|
9
|
+
different organizations are comparable, replicable, and verifiable.
|
|
10
|
+
|
|
11
|
+
Proposed by [ELDÆON](https://github.com/disclosurefoundation/disclosureos/pull/5)
|
|
12
|
+
and promoted into the framework as a foundation package.
|
|
13
|
+
|
|
14
|
+
DisclosureOS is a **six-part standard**. Each part answers one question about an
|
|
15
|
+
observation; `@disclosureos/schema` binds the package-owned pieces into one portable
|
|
16
|
+
contract (a single TS type + JSON Schema + non-stripping parse).
|
|
17
|
+
|
|
18
|
+
| Part | Package surface | Question it answers |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| **Records** | `@disclosureos/records` | *What was observed?* |
|
|
21
|
+
| **Observables** | `@disclosureos/observables` | *What anomalous characteristics did it show?* |
|
|
22
|
+
| **Origins** | `@disclosureos/origins` | *What might explain it?* |
|
|
23
|
+
| **Claims** | `@disclosureos/records/shared` | *Who assessed it, why, and on what evidence?* |
|
|
24
|
+
| **Scoring** | `@disclosureos/scoring` | *How complete / compelling is the case?* |
|
|
25
|
+
| **Instruments** | `@disclosureos/instruments` | *What hardware produced the data?* |
|
|
26
|
+
|
|
27
|
+
Supporting packages: **`@disclosureos/schema`** (the portable contract that composes the
|
|
28
|
+
package-owned pieces), **`@disclosureos/cli`** (tooling), and
|
|
29
|
+
**`@disclosureos/examples`** (the runnable golden path). *(You are here: **Instruments**.)*
|
|
30
|
+
|
|
31
|
+
> **See it end to end.** [`examples/golden-path.ts`](../../examples/golden-path.ts)
|
|
32
|
+
> takes one observation through every part — including a sensor manifest cited via
|
|
33
|
+
> `SensorReading.sensorRef` — in a single type-checked file. Run it with
|
|
34
|
+
> `pnpm --filter @disclosureos/examples golden-path`.
|
|
35
|
+
|
|
36
|
+
## The manifest is a standalone document
|
|
37
|
+
|
|
38
|
+
Unlike `observables` and `origins`, this package does not add a slot to
|
|
39
|
+
`Observation`. A `SensorManifest` is the standard's first standalone document
|
|
40
|
+
type: each organization publishes its own manifest (a catalog of its sensors),
|
|
41
|
+
and observations point at manifest entries from sensor readings:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createSensorReading } from '@disclosureos/records/factories';
|
|
45
|
+
import { sensorRef } from '@disclosureos/records/shared';
|
|
46
|
+
|
|
47
|
+
const reading = createSensorReading('passive_radar', 'radio_frequency', {
|
|
48
|
+
id: 'r1',
|
|
49
|
+
sensorRef: sensorRef('eldaeon', 'dionysus-passive-radar'), // "<org-slug>:<sensor-id>"
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## What each sensor entry captures
|
|
54
|
+
|
|
55
|
+
The functional hardware context `SensorReading` deliberately does not carry:
|
|
56
|
+
|
|
57
|
+
- **Type mapping** — `recordsMapping` bridges each sensor to the
|
|
58
|
+
`@disclosureos/records` `SensorType`/`DetectionMethod` enums; values outside
|
|
59
|
+
those enums must carry a `proposedSensorType`/`proposedDetectionMethod` flag.
|
|
60
|
+
- **Timing provenance** — clock source (`atomic_clock`, `gps_disciplined`, …) and
|
|
61
|
+
timestamp uncertainty. Multi-station correlation requires declared, not
|
|
62
|
+
assumed, timing.
|
|
63
|
+
- **Measurements + uncertainty** — measured quantities with UCUM-style units and
|
|
64
|
+
GUM uncertainty (`u_c`, `U`, `k`, type A/B).
|
|
65
|
+
- **Raw-data locators** — format and path convention, supporting a
|
|
66
|
+
metadata-first architecture (circulate manifests widely, pull raw data on
|
|
67
|
+
demand).
|
|
68
|
+
- **Calibration provenance** — the package's centerpiece. `currentMethod` (what
|
|
69
|
+
the operator actually does today) is separated from `traceableReference` +
|
|
70
|
+
`referenceInUse` (the reference it has identified, and whether it is used),
|
|
71
|
+
under a maturity gradient:
|
|
72
|
+
|
|
73
|
+
`none → candidate_identified → in_practice → documented`
|
|
74
|
+
|
|
75
|
+
Declaring "no calibration" is valid and *useful* — the degree of calibration
|
|
76
|
+
is known, which is the scientific requirement. Honest nulls are first-class
|
|
77
|
+
throughout the calibration block.
|
|
78
|
+
|
|
79
|
+
## Install
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pnpm add @disclosureos/instruments zod
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import {
|
|
89
|
+
createSensorEntry,
|
|
90
|
+
createSensorManifest,
|
|
91
|
+
validateSensorManifest,
|
|
92
|
+
formatSensorManifest,
|
|
93
|
+
} from '@disclosureos/instruments';
|
|
94
|
+
|
|
95
|
+
const radar = createSensorEntry('dionysus-passive-radar', 'Passive Bistatic Radar', 'radio_frequency', {
|
|
96
|
+
recordsMapping: { sensorType: 'passive_radar', detectionMethod: 'radio_frequency' },
|
|
97
|
+
timing: { timeSource: 'gps_disciplined' },
|
|
98
|
+
calibration: {
|
|
99
|
+
status: 'in_practice',
|
|
100
|
+
currentMethod: 'continuous ADS-B truth association with match residuals recorded',
|
|
101
|
+
traceableReference: 'ADS-B Exchange',
|
|
102
|
+
referenceInUse: true,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const manifest = createSensorManifest('ELDÆON', 'eldaeon', [radar]);
|
|
107
|
+
|
|
108
|
+
validateSensorManifest(manifest); // [] when valid — flat ValidationIssue[] otherwise
|
|
109
|
+
formatSensorManifest(manifest); // "ELDÆON — 1 sensor across 1 modality"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Validate manifest files from the command line:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pnpm dlx @disclosureos/cli manifest validate ./manifests/eldaeon-sensors.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## JSON Schema
|
|
119
|
+
|
|
120
|
+
The package emits a committed, drift-tested JSON Schema artifact
|
|
121
|
+
(`schema/sensor-manifest.schema.json`) hosted at:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
https://os.disclosure.org/schema/instruments/1.0.0/sensor-manifest.json
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Non-TS toolchains validate manifests against that `$id` directly.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT © Disclosure Foundation
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
declare const MODALITIES: ("audio" | "electro_optical" | "radio_frequency" | "quantum" | "environmental" | "biometric")[];
|
|
2
|
+
declare const TIME_SOURCES: ("atomic_clock" | "gps_disciplined" | "ntp" | "system" | "unknown")[];
|
|
3
|
+
declare const CALIBRATION_STATUSES: ("none" | "candidate_identified" | "in_practice" | "documented")[];
|
|
4
|
+
declare const UPGRADE_STATUSES: ("planned" | "evaluating" | "ordered" | "acquired")[];
|
|
5
|
+
declare const UNCERTAINTY_TYPES: ("A" | "B")[];
|
|
6
|
+
|
|
7
|
+
export { CALIBRATION_STATUSES, MODALITIES, TIME_SOURCES, UNCERTAINTY_TYPES, UPGRADE_STATUSES };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
// src/manifest/types.ts
|
|
4
|
+
var KEBAB_CASE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
5
|
+
var ModalitySchema = z.enum(["audio", "electro_optical", "radio_frequency", "quantum", "environmental", "biometric"]).describe("Top-level sensing modality the sensor belongs to.");
|
|
6
|
+
var TimeSourceSchema = z.enum(["atomic_clock", "gps_disciplined", "ntp", "system", "unknown"]).describe("Clock source that timestamps the sensor\u2019s data.");
|
|
7
|
+
var SensorTimingSchema = z.object({
|
|
8
|
+
timeSource: TimeSourceSchema,
|
|
9
|
+
timeUncertaintyNs: z.number().nullable().optional().describe("Timestamp uncertainty in nanoseconds. Null = not yet characterized.")
|
|
10
|
+
}).meta({ id: "SensorTiming" }).describe(
|
|
11
|
+
"Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed."
|
|
12
|
+
);
|
|
13
|
+
var RecordsMappingSchema = z.object({
|
|
14
|
+
sensorType: z.string().optional().describe("The `@disclosureos/records` SensorType this sensor maps to."),
|
|
15
|
+
detectionMethod: z.string().optional().describe("The `@disclosureos/records` DetectionMethod this sensor maps to."),
|
|
16
|
+
proposedSensorType: z.boolean().optional().describe("True = sensorType is not in the records enum yet and is proposed by the publisher."),
|
|
17
|
+
proposedDetectionMethod: z.boolean().optional().describe("True = detectionMethod is not in the records enum yet and is proposed by the publisher.")
|
|
18
|
+
}).meta({ id: "RecordsMapping" }).describe(
|
|
19
|
+
"How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag."
|
|
20
|
+
);
|
|
21
|
+
var RawDataSpecSchema = z.object({
|
|
22
|
+
format: z.string().optional().describe('Raw-data file format, e.g. "NDJSON.gz", "WAV", "MJPEG", "FITS", "CSV".'),
|
|
23
|
+
locatorPattern: z.string().nullable().optional().describe("Storage key pattern or path convention for locating the raw files."),
|
|
24
|
+
sampleRateHz: z.number().nullable().optional().describe("Sample rate in Hz, where applicable."),
|
|
25
|
+
bitDepth: z.number().nullable().optional().describe("Sample bit depth, where applicable.")
|
|
26
|
+
}).meta({ id: "RawDataSpec" }).describe(
|
|
27
|
+
"Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand."
|
|
28
|
+
);
|
|
29
|
+
var UncertaintyTypeSchema = z.enum(["A", "B"]).describe("GUM uncertainty evaluation type: A (statistical) or B (other means).");
|
|
30
|
+
var MeasurementUncertaintySchema = z.object({
|
|
31
|
+
u_c: z.number().nullable().optional().describe("Combined standard uncertainty."),
|
|
32
|
+
U: z.number().nullable().optional().describe("Expanded uncertainty (= k \xD7 u_c)."),
|
|
33
|
+
k: z.number().nullable().optional().describe("Coverage factor (2 \u2248 95% confidence level)."),
|
|
34
|
+
type: UncertaintyTypeSchema.nullable().optional()
|
|
35
|
+
}).meta({ id: "MeasurementUncertainty" }).describe(
|
|
36
|
+
'GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists \u2014 declaring "unknown" honestly is itself information.'
|
|
37
|
+
);
|
|
38
|
+
var MeasurementSchema = z.object({
|
|
39
|
+
name: z.string().min(1).describe('Measured quantity, e.g. "differential_pressure".'),
|
|
40
|
+
unit: z.string().min(1).describe('UCUM-style unit string, e.g. "Pa", "dB", "uT", "ppm", "/min".'),
|
|
41
|
+
uncertainty: MeasurementUncertaintySchema.optional()
|
|
42
|
+
}).meta({ id: "Measurement" }).describe("One measured quantity with its unit and uncertainty.");
|
|
43
|
+
var CalibrationStatusSchema = z.enum(["none", "candidate_identified", "in_practice", "documented"]).describe(
|
|
44
|
+
"Calibration maturity gradient: none = no calibration; candidate_identified = a reference is named but not used; in_practice = a real method is performed but not fully budgeted; documented = method + uncertainty budget published."
|
|
45
|
+
);
|
|
46
|
+
var SensorCalibrationSchema = z.object({
|
|
47
|
+
status: CalibrationStatusSchema,
|
|
48
|
+
calibrated: z.boolean().nullable().optional().describe("Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined."),
|
|
49
|
+
currentMethod: z.string().nullable().optional().describe("What the operator actually does today. Null = no calibration currently performed."),
|
|
50
|
+
traceableReference: z.string().nullable().optional().describe('Traceable reference, in use or identified as a candidate (e.g. "GPS/UTC", "USGS/INTERMAGNET").'),
|
|
51
|
+
referenceInUse: z.boolean().nullable().optional().describe("True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined."),
|
|
52
|
+
cadence: z.string().nullable().optional().describe("How often calibration is performed."),
|
|
53
|
+
uncertaintyBudget: z.string().nullable().optional().describe("Published uncertainty budget, if any."),
|
|
54
|
+
notes: z.string().nullable().optional().describe("Open questions or method caveats.")
|
|
55
|
+
}).meta({ id: "SensorCalibration" }).describe(
|
|
56
|
+
"Calibration provenance. Deliberately separates what an operator actually does today from the reference it has identified; honest nulls are first-class, so calibration gaps stay visible and comparable across operators."
|
|
57
|
+
);
|
|
58
|
+
var SensorEntrySchema = z.object({
|
|
59
|
+
id: z.string().regex(KEBAB_CASE_PATTERN).describe(
|
|
60
|
+
'Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` ("<org-slug>:<sensor-id>").'
|
|
61
|
+
),
|
|
62
|
+
name: z.string().min(1).describe("Human-readable sensor name."),
|
|
63
|
+
modality: ModalitySchema,
|
|
64
|
+
manufacturerModel: z.string().optional().describe(
|
|
65
|
+
'Hardware class descriptor. Publishers MAY withhold specific make/model identities and publish spec-level class descriptors instead (e.g. "dual GM-tube counter" rather than a product name).'
|
|
66
|
+
),
|
|
67
|
+
inHouse: z.boolean().optional().describe("True if operator-built rather than off-the-shelf."),
|
|
68
|
+
compute: z.string().optional().describe("The compute unit this sensor is attached to, for platforms with several compute nodes."),
|
|
69
|
+
recordsMapping: RecordsMappingSchema.optional(),
|
|
70
|
+
timing: SensorTimingSchema.optional(),
|
|
71
|
+
rawData: RawDataSpecSchema.optional(),
|
|
72
|
+
measurements: z.array(MeasurementSchema).optional(),
|
|
73
|
+
calibration: SensorCalibrationSchema.optional(),
|
|
74
|
+
specs: z.record(z.string(), z.unknown()).optional().describe(
|
|
75
|
+
"Free-form hardware specifications from the operator\u2019s spec sheet (resolution, range, sensitivity, interface, \u2026). Keys vary by modality."
|
|
76
|
+
),
|
|
77
|
+
specSource: z.string().optional().describe("Provenance of the spec values.")
|
|
78
|
+
}).meta({ id: "SensorEntry" }).describe("One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.");
|
|
79
|
+
var UpgradeStatusSchema = z.enum(["planned", "evaluating", "ordered", "acquired"]).describe("Acquisition status of a declared future hardware upgrade.");
|
|
80
|
+
var FutureUpgradeSchema = z.object({
|
|
81
|
+
name: z.string().min(1),
|
|
82
|
+
modality: ModalitySchema,
|
|
83
|
+
status: UpgradeStatusSchema.optional(),
|
|
84
|
+
specs: z.record(z.string(), z.unknown()).optional(),
|
|
85
|
+
link: z.string().nullable().optional().describe("Public product or reference page, where the publisher chooses to share one."),
|
|
86
|
+
notes: z.string().nullable().optional()
|
|
87
|
+
}).meta({ id: "FutureUpgrade" }).describe(
|
|
88
|
+
"Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array."
|
|
89
|
+
);
|
|
90
|
+
z.object({
|
|
91
|
+
schemaVersion: z.string().min(1).describe("Version of the sensor-manifest schema this instance targets (SemVer)."),
|
|
92
|
+
org: z.string().min(1).describe('Publishing organization, display form (e.g. "ELD\xC6ON").'),
|
|
93
|
+
orgSlug: z.string().regex(KEBAB_CASE_PATTERN).describe('Stable lowercase slug for the publisher (e.g. "eldaeon"); the org half of a `sensorRef`.'),
|
|
94
|
+
orgUrl: z.string().optional().describe("URL for the publishing organization."),
|
|
95
|
+
generatedAt: z.string().optional().describe("ISO date the manifest was generated."),
|
|
96
|
+
sensors: z.array(SensorEntrySchema).min(1),
|
|
97
|
+
futureUpgrades: z.array(FutureUpgradeSchema).optional()
|
|
98
|
+
}).meta({ id: "SensorManifest" }).describe(
|
|
99
|
+
"A published catalog of one organization\u2019s detection hardware. Any operator \u2014 vendor, research group, or institution \u2014 publishes its own manifest against this schema so datasets from different sensor arrays can be compared directly."
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// src/constants/index.ts
|
|
103
|
+
var MODALITIES = ModalitySchema.options;
|
|
104
|
+
var TIME_SOURCES = TimeSourceSchema.options;
|
|
105
|
+
var CALIBRATION_STATUSES = CalibrationStatusSchema.options;
|
|
106
|
+
var UPGRADE_STATUSES = UpgradeStatusSchema.options;
|
|
107
|
+
var UNCERTAINTY_TYPES = UncertaintyTypeSchema.options;
|
|
108
|
+
|
|
109
|
+
export { CALIBRATION_STATUSES, MODALITIES, TIME_SOURCES, UNCERTAINTY_TYPES, UPGRADE_STATUSES };
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
111
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/manifest/types.ts","../../src/constants/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * The sensor manifest is the instrument layer of the standard: DisclosureOS\n * records describe *what was observed*; a sensor manifest describes *the\n * hardware that produced the data* — per sensor, in enough structured detail\n * that a field mission or data drop from one organization is comparable,\n * replicable, and verifiable by everyone else.\n *\n * Design lineage: proposed by ELDÆON (disclosurefoundation/disclosureos#5) and\n * promoted into the framework as a foundation package. The manifest is the\n * standard's first standalone document type besides `Observation`: it is not a\n * per-observation extension slot — observations point at manifest entries via\n * `SensorReading.sensorRef` (`\"<org-slug>:<sensor-id>\"`).\n */\n\nconst KEBAB_CASE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;\n\nexport const ModalitySchema = z\n .enum(['audio', 'electro_optical', 'radio_frequency', 'quantum', 'environmental', 'biometric'])\n .describe('Top-level sensing modality the sensor belongs to.');\n\nexport type Modality = z.infer<typeof ModalitySchema>;\n\nexport const TimeSourceSchema = z\n .enum(['atomic_clock', 'gps_disciplined', 'ntp', 'system', 'unknown'])\n .describe('Clock source that timestamps the sensor\\u2019s data.');\n\nexport type TimeSource = z.infer<typeof TimeSourceSchema>;\n\nexport const SensorTimingSchema = z\n .object({\n timeSource: TimeSourceSchema,\n timeUncertaintyNs: z\n .number()\n .nullable()\n .optional()\n .describe('Timestamp uncertainty in nanoseconds. Null = not yet characterized.'),\n })\n .meta({ id: 'SensorTiming' })\n .describe(\n 'Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed.',\n );\n\nexport type SensorTiming = z.infer<typeof SensorTimingSchema>;\n\nexport const RecordsMappingSchema = z\n .object({\n sensorType: z\n .string()\n .optional()\n .describe('The `@disclosureos/records` SensorType this sensor maps to.'),\n detectionMethod: z\n .string()\n .optional()\n .describe('The `@disclosureos/records` DetectionMethod this sensor maps to.'),\n proposedSensorType: z\n .boolean()\n .optional()\n .describe('True = sensorType is not in the records enum yet and is proposed by the publisher.'),\n proposedDetectionMethod: z\n .boolean()\n .optional()\n .describe('True = detectionMethod is not in the records enum yet and is proposed by the publisher.'),\n })\n .meta({ id: 'RecordsMapping' })\n .describe(\n 'How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag.',\n );\n\nexport type RecordsMapping = z.infer<typeof RecordsMappingSchema>;\n\nexport const RawDataSpecSchema = z\n .object({\n format: z\n .string()\n .optional()\n .describe('Raw-data file format, e.g. \"NDJSON.gz\", \"WAV\", \"MJPEG\", \"FITS\", \"CSV\".'),\n locatorPattern: z\n .string()\n .nullable()\n .optional()\n .describe('Storage key pattern or path convention for locating the raw files.'),\n sampleRateHz: z.number().nullable().optional().describe('Sample rate in Hz, where applicable.'),\n bitDepth: z.number().nullable().optional().describe('Sample bit depth, where applicable.'),\n })\n .meta({ id: 'RawDataSpec' })\n .describe(\n 'Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand.',\n );\n\nexport type RawDataSpec = z.infer<typeof RawDataSpecSchema>;\n\nexport const UncertaintyTypeSchema = z\n .enum(['A', 'B'])\n .describe('GUM uncertainty evaluation type: A (statistical) or B (other means).');\n\nexport type UncertaintyType = z.infer<typeof UncertaintyTypeSchema>;\n\nexport const MeasurementUncertaintySchema = z\n .object({\n u_c: z.number().nullable().optional().describe('Combined standard uncertainty.'),\n U: z.number().nullable().optional().describe('Expanded uncertainty (= k \\u00d7 u_c).'),\n k: z.number().nullable().optional().describe('Coverage factor (2 \\u2248 95% confidence level).'),\n type: UncertaintyTypeSchema.nullable().optional(),\n })\n .meta({ id: 'MeasurementUncertainty' })\n .describe(\n 'GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists — declaring \"unknown\" honestly is itself information.',\n );\n\nexport type MeasurementUncertainty = z.infer<typeof MeasurementUncertaintySchema>;\n\nexport const MeasurementSchema = z\n .object({\n name: z.string().min(1).describe('Measured quantity, e.g. \"differential_pressure\".'),\n unit: z.string().min(1).describe('UCUM-style unit string, e.g. \"Pa\", \"dB\", \"uT\", \"ppm\", \"/min\".'),\n uncertainty: MeasurementUncertaintySchema.optional(),\n })\n .meta({ id: 'Measurement' })\n .describe('One measured quantity with its unit and uncertainty.');\n\nexport type Measurement = z.infer<typeof MeasurementSchema>;\n\nexport const CalibrationStatusSchema = z\n .enum(['none', 'candidate_identified', 'in_practice', 'documented'])\n .describe(\n 'Calibration maturity gradient: none = no calibration; candidate_identified = a reference is named but not used; in_practice = a real method is performed but not fully budgeted; documented = method + uncertainty budget published.',\n );\n\nexport type CalibrationStatus = z.infer<typeof CalibrationStatusSchema>;\n\nexport const SensorCalibrationSchema = z\n .object({\n status: CalibrationStatusSchema,\n calibrated: z\n .boolean()\n .nullable()\n .optional()\n .describe('Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined.'),\n currentMethod: z\n .string()\n .nullable()\n .optional()\n .describe('What the operator actually does today. Null = no calibration currently performed.'),\n traceableReference: z\n .string()\n .nullable()\n .optional()\n .describe('Traceable reference, in use or identified as a candidate (e.g. \"GPS/UTC\", \"USGS/INTERMAGNET\").'),\n referenceInUse: z\n .boolean()\n .nullable()\n .optional()\n .describe('True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined.'),\n cadence: z.string().nullable().optional().describe('How often calibration is performed.'),\n uncertaintyBudget: z.string().nullable().optional().describe('Published uncertainty budget, if any.'),\n notes: z.string().nullable().optional().describe('Open questions or method caveats.'),\n })\n .meta({ id: 'SensorCalibration' })\n .describe(\n 'Calibration provenance. Deliberately separates what an operator actually does today from the reference it has identified; honest nulls are first-class, so calibration gaps stay visible and comparable across operators.',\n );\n\nexport type SensorCalibration = z.infer<typeof SensorCalibrationSchema>;\n\nexport const SensorEntrySchema = z\n .object({\n id: z\n .string()\n .regex(KEBAB_CASE_PATTERN)\n .describe(\n 'Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` (\"<org-slug>:<sensor-id>\").',\n ),\n name: z.string().min(1).describe('Human-readable sensor name.'),\n modality: ModalitySchema,\n manufacturerModel: z\n .string()\n .optional()\n .describe(\n 'Hardware class descriptor. Publishers MAY withhold specific make/model identities and publish spec-level class descriptors instead (e.g. \"dual GM-tube counter\" rather than a product name).',\n ),\n inHouse: z.boolean().optional().describe('True if operator-built rather than off-the-shelf.'),\n compute: z\n .string()\n .optional()\n .describe('The compute unit this sensor is attached to, for platforms with several compute nodes.'),\n recordsMapping: RecordsMappingSchema.optional(),\n timing: SensorTimingSchema.optional(),\n rawData: RawDataSpecSchema.optional(),\n measurements: z.array(MeasurementSchema).optional(),\n calibration: SensorCalibrationSchema.optional(),\n specs: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Free-form hardware specifications from the operator\\u2019s spec sheet (resolution, range, sensitivity, interface, \\u2026). Keys vary by modality.',\n ),\n specSource: z.string().optional().describe('Provenance of the spec values.'),\n })\n .meta({ id: 'SensorEntry' })\n .describe('One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.');\n\nexport type SensorEntry = z.infer<typeof SensorEntrySchema>;\n\nexport const UpgradeStatusSchema = z\n .enum(['planned', 'evaluating', 'ordered', 'acquired'])\n .describe('Acquisition status of a declared future hardware upgrade.');\n\nexport type UpgradeStatus = z.infer<typeof UpgradeStatusSchema>;\n\nexport const FutureUpgradeSchema = z\n .object({\n name: z.string().min(1),\n modality: ModalitySchema,\n status: UpgradeStatusSchema.optional(),\n specs: z.record(z.string(), z.unknown()).optional(),\n link: z.string().nullable().optional().describe('Public product or reference page, where the publisher chooses to share one.'),\n notes: z.string().nullable().optional(),\n })\n .meta({ id: 'FutureUpgrade' })\n .describe(\n 'Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array.',\n );\n\nexport type FutureUpgrade = z.infer<typeof FutureUpgradeSchema>;\n\nexport const SensorManifestSchema = z\n .object({\n schemaVersion: z.string().min(1).describe('Version of the sensor-manifest schema this instance targets (SemVer).'),\n org: z.string().min(1).describe('Publishing organization, display form (e.g. \"ELD\\u00c6ON\").'),\n orgSlug: z\n .string()\n .regex(KEBAB_CASE_PATTERN)\n .describe('Stable lowercase slug for the publisher (e.g. \"eldaeon\"); the org half of a `sensorRef`.'),\n orgUrl: z.string().optional().describe('URL for the publishing organization.'),\n generatedAt: z.string().optional().describe('ISO date the manifest was generated.'),\n sensors: z.array(SensorEntrySchema).min(1),\n futureUpgrades: z.array(FutureUpgradeSchema).optional(),\n })\n .meta({ id: 'SensorManifest' })\n .describe(\n 'A published catalog of one organization\\u2019s detection hardware. Any operator — vendor, research group, or institution — publishes its own manifest against this schema so datasets from different sensor arrays can be compared directly.',\n );\n\nexport type SensorManifest = z.infer<typeof SensorManifestSchema>;\n","import {\n ModalitySchema,\n TimeSourceSchema,\n CalibrationStatusSchema,\n UpgradeStatusSchema,\n UncertaintyTypeSchema,\n} from '../manifest/types';\n\nexport const MODALITIES = ModalitySchema.options;\nexport const TIME_SOURCES = TimeSourceSchema.options;\nexport const CALIBRATION_STATUSES = CalibrationStatusSchema.options;\nexport const UPGRADE_STATUSES = UpgradeStatusSchema.options;\nexport const UNCERTAINTY_TYPES = UncertaintyTypeSchema.options;\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Modality, SensorEntry, SensorManifest } from '../manifest/index.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build a sensor entry from the three required fields, with everything else
|
|
6
|
+
* supplied via `options`.
|
|
7
|
+
*/
|
|
8
|
+
declare function createSensorEntry(id: string, name: string, modality: Modality, options?: Partial<Omit<SensorEntry, 'id' | 'name' | 'modality'>>): SensorEntry;
|
|
9
|
+
/**
|
|
10
|
+
* Build a sensor manifest. `schemaVersion` defaults to the version of the
|
|
11
|
+
* schema this package emits.
|
|
12
|
+
*/
|
|
13
|
+
declare function createSensorManifest(org: string, orgSlug: string, sensors: SensorEntry[], options?: Partial<Omit<SensorManifest, 'org' | 'orgSlug' | 'sensors'>>): SensorManifest;
|
|
14
|
+
|
|
15
|
+
export { createSensorEntry, createSensorManifest };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import 'zod';
|
|
2
|
+
import { schemaId } from '@disclosureos/records/shared';
|
|
3
|
+
|
|
4
|
+
// src/schema.ts
|
|
5
|
+
var INSTRUMENTS_SCHEMA_VERSION = "1.0.0";
|
|
6
|
+
schemaId(
|
|
7
|
+
"instruments",
|
|
8
|
+
"sensor-manifest",
|
|
9
|
+
INSTRUMENTS_SCHEMA_VERSION
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
// src/factories/index.ts
|
|
13
|
+
function createSensorEntry(id, name, modality, options) {
|
|
14
|
+
return { id, name, modality, ...options };
|
|
15
|
+
}
|
|
16
|
+
function createSensorManifest(org, orgSlug, sensors, options) {
|
|
17
|
+
return {
|
|
18
|
+
schemaVersion: INSTRUMENTS_SCHEMA_VERSION,
|
|
19
|
+
org,
|
|
20
|
+
orgSlug,
|
|
21
|
+
sensors,
|
|
22
|
+
...options
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { createSensorEntry, createSensorManifest };
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/schema.ts","../../src/factories/index.ts"],"names":[],"mappings":";;;;AASO,IAAM,0BAAA,GAA6B,OAAA;AAEL,QAAA;AAAA,EACnC,aAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF;;;ACRO,SAAS,iBAAA,CACd,EAAA,EACA,IAAA,EACA,QAAA,EACA,OAAA,EACa;AACb,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,QAAA,EAAU,GAAG,OAAA,EAAQ;AAC1C;AAMO,SAAS,oBAAA,CACd,GAAA,EACA,OAAA,EACA,OAAA,EACA,OAAA,EACgB;AAChB,EAAA,OAAO;AAAA,IACL,aAAA,EAAe,0BAAA;AAAA,IACf,GAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,GAAG;AAAA,GACL;AACF","file":"index.js","sourcesContent":["import { z } from 'zod';\nimport { jsonSchemaEnvelope, schemaId } from '@disclosureos/records/shared';\nimport { SensorManifestSchema } from './manifest/types';\n\n/**\n * Version of the emitted JSON Schema artifact. Bump on any intentional change\n * to the manifest shape; the committed `schema/sensor-manifest.schema.json` and\n * the drift test (`src/__tests__/schema.test.ts`) keep this honest.\n */\nexport const INSTRUMENTS_SCHEMA_VERSION = '1.0.0';\n\nexport const INSTRUMENTS_SCHEMA_ID = schemaId(\n 'instruments',\n 'sensor-manifest',\n INSTRUMENTS_SCHEMA_VERSION,\n);\n\n/**\n * Emit the canonical JSON Schema (draft 2020-12) for {@link SensorManifestSchema}.\n * Unlike the satellite slot schemas, this is a standalone document schema — a\n * manifest is published on its own, not composed into `Observation`.\n */\nexport function instrumentsJsonSchema(): Record<string, unknown> {\n const schema = z.toJSONSchema(SensorManifestSchema, { target: 'draft-2020-12' }) as Record<\n string,\n unknown\n >;\n return jsonSchemaEnvelope(schema, {\n id: INSTRUMENTS_SCHEMA_ID,\n version: INSTRUMENTS_SCHEMA_VERSION,\n });\n}\n","import type { Modality, SensorEntry, SensorManifest } from '../manifest/types';\nimport { INSTRUMENTS_SCHEMA_VERSION } from '../schema';\n\n/**\n * Build a sensor entry from the three required fields, with everything else\n * supplied via `options`.\n */\nexport function createSensorEntry(\n id: string,\n name: string,\n modality: Modality,\n options?: Partial<Omit<SensorEntry, 'id' | 'name' | 'modality'>>,\n): SensorEntry {\n return { id, name, modality, ...options };\n}\n\n/**\n * Build a sensor manifest. `schemaVersion` defaults to the version of the\n * schema this package emits.\n */\nexport function createSensorManifest(\n org: string,\n orgSlug: string,\n sensors: SensorEntry[],\n options?: Partial<Omit<SensorManifest, 'org' | 'orgSlug' | 'sensors'>>,\n): SensorManifest {\n return {\n schemaVersion: INSTRUMENTS_SCHEMA_VERSION,\n org,\n orgSlug,\n sensors,\n ...options,\n };\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CalibrationStatus, Modality, SensorEntry, SensorManifest } from '../manifest/index.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
declare function formatModality(modality: Modality): string;
|
|
5
|
+
declare function formatCalibrationStatus(status: CalibrationStatus): string;
|
|
6
|
+
/** One-line sensor summary, e.g. `"Passive Bistatic Radar (Radio Frequency) — calibration: In Practice"`. */
|
|
7
|
+
declare function formatSensorEntry(sensor: SensorEntry): string;
|
|
8
|
+
/** One-line manifest summary, e.g. `"ELDÆON — 28 sensors across 6 modalities, 3 future upgrades"`. */
|
|
9
|
+
declare function formatSensorManifest(manifest: SensorManifest): string;
|
|
10
|
+
|
|
11
|
+
export { formatCalibrationStatus, formatModality, formatSensorEntry, formatSensorManifest };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/labels/index.ts
|
|
2
|
+
var MODALITY_LABELS = {
|
|
3
|
+
audio: "Audio",
|
|
4
|
+
electro_optical: "Electro-Optical",
|
|
5
|
+
radio_frequency: "Radio Frequency",
|
|
6
|
+
quantum: "Quantum",
|
|
7
|
+
environmental: "Environmental",
|
|
8
|
+
biometric: "Biometric"
|
|
9
|
+
};
|
|
10
|
+
var CALIBRATION_STATUS_LABELS = {
|
|
11
|
+
none: "None",
|
|
12
|
+
candidate_identified: "Candidate Identified",
|
|
13
|
+
in_practice: "In Practice",
|
|
14
|
+
documented: "Documented"
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/formatters/index.ts
|
|
18
|
+
function formatModality(modality) {
|
|
19
|
+
return MODALITY_LABELS[modality];
|
|
20
|
+
}
|
|
21
|
+
function formatCalibrationStatus(status) {
|
|
22
|
+
return CALIBRATION_STATUS_LABELS[status];
|
|
23
|
+
}
|
|
24
|
+
function formatSensorEntry(sensor) {
|
|
25
|
+
const calibration = sensor.calibration ? ` \u2014 calibration: ${formatCalibrationStatus(sensor.calibration.status)}` : "";
|
|
26
|
+
return `${sensor.name} (${formatModality(sensor.modality)})${calibration}`;
|
|
27
|
+
}
|
|
28
|
+
function formatSensorManifest(manifest) {
|
|
29
|
+
const modalityCount = new Set(manifest.sensors.map((sensor) => sensor.modality)).size;
|
|
30
|
+
const sensorCount = manifest.sensors.length;
|
|
31
|
+
const upgrades = manifest.futureUpgrades?.length ?? 0;
|
|
32
|
+
const upgradeSuffix = upgrades > 0 ? `, ${upgrades} future upgrade${upgrades === 1 ? "" : "s"}` : "";
|
|
33
|
+
return `${manifest.org} \u2014 ${sensorCount} sensor${sensorCount === 1 ? "" : "s"} across ${modalityCount} modalit${modalityCount === 1 ? "y" : "ies"}${upgradeSuffix}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { formatCalibrationStatus, formatModality, formatSensorEntry, formatSensorManifest };
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/labels/index.ts","../../src/formatters/index.ts"],"names":[],"mappings":";AAEO,IAAM,eAAA,GAA4C;AAAA,EACvD,KAAA,EAAO,OAAA;AAAA,EACP,eAAA,EAAiB,iBAAA;AAAA,EACjB,eAAA,EAAiB,iBAAA;AAAA,EACjB,OAAA,EAAS,SAAA;AAAA,EACT,aAAA,EAAe,eAAA;AAAA,EACf,SAAA,EAAW;AACb,CAAA;AAUO,IAAM,yBAAA,GAA+D;AAAA,EAC1E,IAAA,EAAM,MAAA;AAAA,EACN,oBAAA,EAAsB,sBAAA;AAAA,EACtB,WAAA,EAAa,aAAA;AAAA,EACb,UAAA,EAAY;AACd,CAAA;;;ACrBO,SAAS,eAAe,QAAA,EAA4B;AACzD,EAAA,OAAO,gBAAgB,QAAQ,CAAA;AACjC;AAEO,SAAS,wBAAwB,MAAA,EAAmC;AACzE,EAAA,OAAO,0BAA0B,MAAM,CAAA;AACzC;AAGO,SAAS,kBAAkB,MAAA,EAA6B;AAC7D,EAAA,MAAM,WAAA,GAAc,OAAO,WAAA,GACvB,CAAA,qBAAA,EAAmB,wBAAwB,MAAA,CAAO,WAAA,CAAY,MAAM,CAAC,CAAA,CAAA,GACrE,EAAA;AACJ,EAAA,OAAO,CAAA,EAAG,OAAO,IAAI,CAAA,EAAA,EAAK,eAAe,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAC1E;AAGO,SAAS,qBAAqB,QAAA,EAAkC;AACrE,EAAA,MAAM,aAAA,GAAgB,IAAI,GAAA,CAAI,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAE,IAAA;AACjF,EAAA,MAAM,WAAA,GAAc,SAAS,OAAA,CAAQ,MAAA;AACrC,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,cAAA,EAAgB,MAAA,IAAU,CAAA;AACpD,EAAA,MAAM,aAAA,GAAgB,QAAA,GAAW,CAAA,GAAI,CAAA,EAAA,EAAK,QAAQ,kBAAkB,QAAA,KAAa,CAAA,GAAI,EAAA,GAAK,GAAG,CAAA,CAAA,GAAK,EAAA;AAClG,EAAA,OAAO,GAAG,QAAA,CAAS,GAAG,WAAM,WAAW,CAAA,OAAA,EAAU,gBAAgB,CAAA,GAAI,EAAA,GAAK,GAAG,CAAA,QAAA,EAAW,aAAa,CAAA,QAAA,EAAW,aAAA,KAAkB,IAAI,GAAA,GAAM,KAAK,GAAG,aAAa,CAAA,CAAA;AACnK","file":"index.js","sourcesContent":["import type { Modality, TimeSource, CalibrationStatus, UpgradeStatus } from '../manifest/types';\n\nexport const MODALITY_LABELS: Record<Modality, string> = {\n audio: 'Audio',\n electro_optical: 'Electro-Optical',\n radio_frequency: 'Radio Frequency',\n quantum: 'Quantum',\n environmental: 'Environmental',\n biometric: 'Biometric',\n};\n\nexport const TIME_SOURCE_LABELS: Record<TimeSource, string> = {\n atomic_clock: 'Atomic Clock',\n gps_disciplined: 'GPS-Disciplined',\n ntp: 'NTP',\n system: 'System Clock',\n unknown: 'Unknown',\n};\n\nexport const CALIBRATION_STATUS_LABELS: Record<CalibrationStatus, string> = {\n none: 'None',\n candidate_identified: 'Candidate Identified',\n in_practice: 'In Practice',\n documented: 'Documented',\n};\n\n/** What each rung of the calibration maturity gradient means for a data consumer. */\nexport const CALIBRATION_STATUS_DESCRIPTIONS: Record<CalibrationStatus, string> = {\n none: 'No calibration is performed. Declared honestly, this is itself useful information.',\n candidate_identified: 'A traceable reference has been named but is not yet part of practice.',\n in_practice: 'A real calibration method is performed today, but no full uncertainty budget exists.',\n documented: 'The calibration method and its uncertainty budget are published.',\n};\n\nexport const UPGRADE_STATUS_LABELS: Record<UpgradeStatus, string> = {\n planned: 'Planned',\n evaluating: 'Evaluating',\n ordered: 'Ordered',\n acquired: 'Acquired',\n};\n","import type { CalibrationStatus, Modality, SensorEntry, SensorManifest } from '../manifest/types';\nimport { MODALITY_LABELS, CALIBRATION_STATUS_LABELS } from '../labels';\n\nexport function formatModality(modality: Modality): string {\n return MODALITY_LABELS[modality];\n}\n\nexport function formatCalibrationStatus(status: CalibrationStatus): string {\n return CALIBRATION_STATUS_LABELS[status];\n}\n\n/** One-line sensor summary, e.g. `\"Passive Bistatic Radar (Radio Frequency) — calibration: In Practice\"`. */\nexport function formatSensorEntry(sensor: SensorEntry): string {\n const calibration = sensor.calibration\n ? ` — calibration: ${formatCalibrationStatus(sensor.calibration.status)}`\n : '';\n return `${sensor.name} (${formatModality(sensor.modality)})${calibration}`;\n}\n\n/** One-line manifest summary, e.g. `\"ELDÆON — 28 sensors across 6 modalities, 3 future upgrades\"`. */\nexport function formatSensorManifest(manifest: SensorManifest): string {\n const modalityCount = new Set(manifest.sensors.map((sensor) => sensor.modality)).size;\n const sensorCount = manifest.sensors.length;\n const upgrades = manifest.futureUpgrades?.length ?? 0;\n const upgradeSuffix = upgrades > 0 ? `, ${upgrades} future upgrade${upgrades === 1 ? '' : 's'}` : '';\n return `${manifest.org} — ${sensorCount} sensor${sensorCount === 1 ? '' : 's'} across ${modalityCount} modalit${modalityCount === 1 ? 'y' : 'ies'}${upgradeSuffix}`;\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const isModality: (value: unknown) => value is "audio" | "electro_optical" | "radio_frequency" | "quantum" | "environmental" | "biometric";
|
|
2
|
+
declare const isTimeSource: (value: unknown) => value is "atomic_clock" | "gps_disciplined" | "ntp" | "system" | "unknown";
|
|
3
|
+
declare const isCalibrationStatus: (value: unknown) => value is "none" | "candidate_identified" | "in_practice" | "documented";
|
|
4
|
+
declare const isUpgradeStatus: (value: unknown) => value is "planned" | "evaluating" | "ordered" | "acquired";
|
|
5
|
+
|
|
6
|
+
export { isCalibrationStatus, isModality, isTimeSource, isUpgradeStatus };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createEnumGuard } from '@disclosureos/records/shared';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
// src/guards/index.ts
|
|
5
|
+
var KEBAB_CASE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
6
|
+
var ModalitySchema = z.enum(["audio", "electro_optical", "radio_frequency", "quantum", "environmental", "biometric"]).describe("Top-level sensing modality the sensor belongs to.");
|
|
7
|
+
var TimeSourceSchema = z.enum(["atomic_clock", "gps_disciplined", "ntp", "system", "unknown"]).describe("Clock source that timestamps the sensor\u2019s data.");
|
|
8
|
+
var SensorTimingSchema = z.object({
|
|
9
|
+
timeSource: TimeSourceSchema,
|
|
10
|
+
timeUncertaintyNs: z.number().nullable().optional().describe("Timestamp uncertainty in nanoseconds. Null = not yet characterized.")
|
|
11
|
+
}).meta({ id: "SensorTiming" }).describe(
|
|
12
|
+
"Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed."
|
|
13
|
+
);
|
|
14
|
+
var RecordsMappingSchema = z.object({
|
|
15
|
+
sensorType: z.string().optional().describe("The `@disclosureos/records` SensorType this sensor maps to."),
|
|
16
|
+
detectionMethod: z.string().optional().describe("The `@disclosureos/records` DetectionMethod this sensor maps to."),
|
|
17
|
+
proposedSensorType: z.boolean().optional().describe("True = sensorType is not in the records enum yet and is proposed by the publisher."),
|
|
18
|
+
proposedDetectionMethod: z.boolean().optional().describe("True = detectionMethod is not in the records enum yet and is proposed by the publisher.")
|
|
19
|
+
}).meta({ id: "RecordsMapping" }).describe(
|
|
20
|
+
"How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag."
|
|
21
|
+
);
|
|
22
|
+
var RawDataSpecSchema = z.object({
|
|
23
|
+
format: z.string().optional().describe('Raw-data file format, e.g. "NDJSON.gz", "WAV", "MJPEG", "FITS", "CSV".'),
|
|
24
|
+
locatorPattern: z.string().nullable().optional().describe("Storage key pattern or path convention for locating the raw files."),
|
|
25
|
+
sampleRateHz: z.number().nullable().optional().describe("Sample rate in Hz, where applicable."),
|
|
26
|
+
bitDepth: z.number().nullable().optional().describe("Sample bit depth, where applicable.")
|
|
27
|
+
}).meta({ id: "RawDataSpec" }).describe(
|
|
28
|
+
"Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand."
|
|
29
|
+
);
|
|
30
|
+
var UncertaintyTypeSchema = z.enum(["A", "B"]).describe("GUM uncertainty evaluation type: A (statistical) or B (other means).");
|
|
31
|
+
var MeasurementUncertaintySchema = z.object({
|
|
32
|
+
u_c: z.number().nullable().optional().describe("Combined standard uncertainty."),
|
|
33
|
+
U: z.number().nullable().optional().describe("Expanded uncertainty (= k \xD7 u_c)."),
|
|
34
|
+
k: z.number().nullable().optional().describe("Coverage factor (2 \u2248 95% confidence level)."),
|
|
35
|
+
type: UncertaintyTypeSchema.nullable().optional()
|
|
36
|
+
}).meta({ id: "MeasurementUncertainty" }).describe(
|
|
37
|
+
'GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists \u2014 declaring "unknown" honestly is itself information.'
|
|
38
|
+
);
|
|
39
|
+
var MeasurementSchema = z.object({
|
|
40
|
+
name: z.string().min(1).describe('Measured quantity, e.g. "differential_pressure".'),
|
|
41
|
+
unit: z.string().min(1).describe('UCUM-style unit string, e.g. "Pa", "dB", "uT", "ppm", "/min".'),
|
|
42
|
+
uncertainty: MeasurementUncertaintySchema.optional()
|
|
43
|
+
}).meta({ id: "Measurement" }).describe("One measured quantity with its unit and uncertainty.");
|
|
44
|
+
var CalibrationStatusSchema = z.enum(["none", "candidate_identified", "in_practice", "documented"]).describe(
|
|
45
|
+
"Calibration maturity gradient: none = no calibration; candidate_identified = a reference is named but not used; in_practice = a real method is performed but not fully budgeted; documented = method + uncertainty budget published."
|
|
46
|
+
);
|
|
47
|
+
var SensorCalibrationSchema = z.object({
|
|
48
|
+
status: CalibrationStatusSchema,
|
|
49
|
+
calibrated: z.boolean().nullable().optional().describe("Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined."),
|
|
50
|
+
currentMethod: z.string().nullable().optional().describe("What the operator actually does today. Null = no calibration currently performed."),
|
|
51
|
+
traceableReference: z.string().nullable().optional().describe('Traceable reference, in use or identified as a candidate (e.g. "GPS/UTC", "USGS/INTERMAGNET").'),
|
|
52
|
+
referenceInUse: z.boolean().nullable().optional().describe("True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined."),
|
|
53
|
+
cadence: z.string().nullable().optional().describe("How often calibration is performed."),
|
|
54
|
+
uncertaintyBudget: z.string().nullable().optional().describe("Published uncertainty budget, if any."),
|
|
55
|
+
notes: z.string().nullable().optional().describe("Open questions or method caveats.")
|
|
56
|
+
}).meta({ id: "SensorCalibration" }).describe(
|
|
57
|
+
"Calibration provenance. Deliberately separates what an operator actually does today from the reference it has identified; honest nulls are first-class, so calibration gaps stay visible and comparable across operators."
|
|
58
|
+
);
|
|
59
|
+
var SensorEntrySchema = z.object({
|
|
60
|
+
id: z.string().regex(KEBAB_CASE_PATTERN).describe(
|
|
61
|
+
'Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` ("<org-slug>:<sensor-id>").'
|
|
62
|
+
),
|
|
63
|
+
name: z.string().min(1).describe("Human-readable sensor name."),
|
|
64
|
+
modality: ModalitySchema,
|
|
65
|
+
manufacturerModel: z.string().optional().describe(
|
|
66
|
+
'Hardware class descriptor. Publishers MAY withhold specific make/model identities and publish spec-level class descriptors instead (e.g. "dual GM-tube counter" rather than a product name).'
|
|
67
|
+
),
|
|
68
|
+
inHouse: z.boolean().optional().describe("True if operator-built rather than off-the-shelf."),
|
|
69
|
+
compute: z.string().optional().describe("The compute unit this sensor is attached to, for platforms with several compute nodes."),
|
|
70
|
+
recordsMapping: RecordsMappingSchema.optional(),
|
|
71
|
+
timing: SensorTimingSchema.optional(),
|
|
72
|
+
rawData: RawDataSpecSchema.optional(),
|
|
73
|
+
measurements: z.array(MeasurementSchema).optional(),
|
|
74
|
+
calibration: SensorCalibrationSchema.optional(),
|
|
75
|
+
specs: z.record(z.string(), z.unknown()).optional().describe(
|
|
76
|
+
"Free-form hardware specifications from the operator\u2019s spec sheet (resolution, range, sensitivity, interface, \u2026). Keys vary by modality."
|
|
77
|
+
),
|
|
78
|
+
specSource: z.string().optional().describe("Provenance of the spec values.")
|
|
79
|
+
}).meta({ id: "SensorEntry" }).describe("One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.");
|
|
80
|
+
var UpgradeStatusSchema = z.enum(["planned", "evaluating", "ordered", "acquired"]).describe("Acquisition status of a declared future hardware upgrade.");
|
|
81
|
+
var FutureUpgradeSchema = z.object({
|
|
82
|
+
name: z.string().min(1),
|
|
83
|
+
modality: ModalitySchema,
|
|
84
|
+
status: UpgradeStatusSchema.optional(),
|
|
85
|
+
specs: z.record(z.string(), z.unknown()).optional(),
|
|
86
|
+
link: z.string().nullable().optional().describe("Public product or reference page, where the publisher chooses to share one."),
|
|
87
|
+
notes: z.string().nullable().optional()
|
|
88
|
+
}).meta({ id: "FutureUpgrade" }).describe(
|
|
89
|
+
"Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array."
|
|
90
|
+
);
|
|
91
|
+
z.object({
|
|
92
|
+
schemaVersion: z.string().min(1).describe("Version of the sensor-manifest schema this instance targets (SemVer)."),
|
|
93
|
+
org: z.string().min(1).describe('Publishing organization, display form (e.g. "ELD\xC6ON").'),
|
|
94
|
+
orgSlug: z.string().regex(KEBAB_CASE_PATTERN).describe('Stable lowercase slug for the publisher (e.g. "eldaeon"); the org half of a `sensorRef`.'),
|
|
95
|
+
orgUrl: z.string().optional().describe("URL for the publishing organization."),
|
|
96
|
+
generatedAt: z.string().optional().describe("ISO date the manifest was generated."),
|
|
97
|
+
sensors: z.array(SensorEntrySchema).min(1),
|
|
98
|
+
futureUpgrades: z.array(FutureUpgradeSchema).optional()
|
|
99
|
+
}).meta({ id: "SensorManifest" }).describe(
|
|
100
|
+
"A published catalog of one organization\u2019s detection hardware. Any operator \u2014 vendor, research group, or institution \u2014 publishes its own manifest against this schema so datasets from different sensor arrays can be compared directly."
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// src/guards/index.ts
|
|
104
|
+
var isModality = createEnumGuard(ModalitySchema.options);
|
|
105
|
+
var isTimeSource = createEnumGuard(TimeSourceSchema.options);
|
|
106
|
+
var isCalibrationStatus = createEnumGuard(CalibrationStatusSchema.options);
|
|
107
|
+
var isUpgradeStatus = createEnumGuard(UpgradeStatusSchema.options);
|
|
108
|
+
|
|
109
|
+
export { isCalibrationStatus, isModality, isTimeSource, isUpgradeStatus };
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
111
|
+
//# sourceMappingURL=index.js.map
|