The README's install line failed: the package was never published, and nothing told npm where the @extant2000 scope lives. A tag like v1.2.3 now publishes to this project's registry with CI_JOB_TOKEN, and the README sets the scope's registry before installing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
149 lines
6.4 KiB
Markdown
149 lines
6.4 KiB
Markdown
# MissionSynth
|
|
|
|
Checks that a mission concept holds together: requirements traced to needs in
|
|
both directions, verification criteria someone can decide, architecture
|
|
options that differ, and a TRL claim capped by evidence.
|
|
|
|
## What it does and why
|
|
|
|
MissionSynth does not write requirements. Turning a concept into candidate
|
|
requirements and architectures is generative work, done by people or by a
|
|
model. What decides whether that output survives a review is whether it holds
|
|
together, and that part can be checked:
|
|
|
|
- every requirement traces to a stated need, and every need to a requirement;
|
|
- every requirement names a verification method and a criterion someone could
|
|
decide;
|
|
- the architecture options differ on at least one stated criterion;
|
|
- the claimed TRL does not exceed what the evidence demonstrates.
|
|
|
|
It is pure: no clock, no I/O and no model calls. Reports use the
|
|
`@extant2000/evidence-record` format. The requirement id is the key a
|
|
downstream traceability tool can pick up.
|
|
|
|
## Derivation, checked both ways
|
|
|
|
The two defects a requirement set tends to have are opposites, and a check in
|
|
one direction finds only one of them.
|
|
|
|
| Defect | Typical of |
|
|
|---|---|
|
|
| Invented: traces to no stated need | A generated set. Producing plausible requirements is easy; producing only warranted ones is not. |
|
|
| Unaddressed need: no requirement covers it | A hand-written set. The needs that get forgotten are the ones nobody enjoys thinking about. |
|
|
|
|
A parent id that does not exist (`dangling-parent`) is its own defect. It is
|
|
the same as no parent, and it looks like traceability.
|
|
|
|
A requirement with no verification method fails, and so does one whose
|
|
criterion cannot be decided. A requirement nobody can fail passes every
|
|
review. `isMeasurable()` is a smell test, not a grammar. It catches the common
|
|
cases ("user-friendly", "acceptable", "intuitive"), but a criterion can be
|
|
unmeasurable without using any of those words, so a clean result does not
|
|
prove the criterion is good.
|
|
|
|
## TRL, capped by evidence
|
|
|
|
Technology Readiness Level is usually self-assessed, and it only goes wrong in
|
|
one direction: nobody claims a level below what they can show. The
|
|
definitions are specific, which is what makes this checkable. Each level names
|
|
the environment something was demonstrated in, and an environment is a fact.
|
|
|
|
```
|
|
TRL 4 component validated in a laboratory
|
|
TRL 5 component validated in a relevant environment
|
|
TRL 6 system or subsystem model demonstrated in a relevant environment
|
|
TRL 7 system prototype demonstrated in an operational environment
|
|
```
|
|
|
|
`EVIDENCE_CEILING` maps each kind of demonstration to the highest level it can
|
|
support. A bench test or a unit test (`lab-bench`) supports TRL 3, so a TRL 6
|
|
claim backed by one is capped at 3. The best evidence sets the ceiling:
|
|
having also written a paper does not drag down a system demonstration. No
|
|
evidence at all returns `null`, not TRL 1, because TRL 1 is itself a claim
|
|
that principles were observed and reported.
|
|
|
|
`maturationPath()` runs from the effective level, not the claimed one, and
|
|
each step names the demonstration that raises the number. A roadmap whose
|
|
steps produce no evidence is a schedule.
|
|
|
|
## A trade study with nothing to trade
|
|
|
|
- **One option** is a decision already made. It is reported as not assessed,
|
|
whatever the document is called.
|
|
- Options identical on every criterion fail at critical severity. The table is
|
|
full, the columns are populated, and the choice rests on something not
|
|
written down, which is why this passes a quick review.
|
|
- Criteria that are the same across all options are named as doing no work in
|
|
the decision. That is a note, not a fault.
|
|
- An option that satisfies a strict subset of another's requirements and adds
|
|
nothing of its own is flagged as dominated. It may still win on cost, but
|
|
carrying it unexamined makes the study look broader than it is.
|
|
- A requirement that no option satisfies fails.
|
|
|
|
## Usage
|
|
|
|
```ts
|
|
import { synthesize, formatSynthesis, type MissionConcept } from '@extant2000/mission-synth'
|
|
|
|
const concept: MissionConcept = {
|
|
name: 'deorbit module',
|
|
needs: [
|
|
{ id: 'N-1', statement: 'deorbit within 25 years of end of mission',
|
|
source: 'debris mitigation guideline', where: 'concept/needs.md' },
|
|
{ id: 'N-2', statement: 'survive launch loads', source: 'launch provider', where: 'concept/needs.md' },
|
|
],
|
|
requirements: [
|
|
{ id: 'SYS-001', statement: 'The system shall deorbit within 25 years', derivedFrom: ['N-1'],
|
|
verification: { method: 'analysis', criterion: 're-entry at less than 25 years' },
|
|
where: 'concept/requirements.md' },
|
|
{ id: 'SYS-002', statement: 'The system shall be easy to integrate', derivedFrom: [],
|
|
verification: { method: 'inspection', criterion: 'integration is intuitive' },
|
|
where: 'concept/requirements.md' },
|
|
],
|
|
options: [
|
|
{ id: 'A', name: 'drag sail', satisfies: ['SYS-001'], criteria: { mass: 'low', cost: 2 }, where: 'trade/a.md' },
|
|
{ id: 'B', name: 'propulsive', satisfies: ['SYS-001'], criteria: { mass: 'low', cost: 2 }, where: 'trade/b.md' },
|
|
],
|
|
claimedTrl: 6,
|
|
targetTrl: 7,
|
|
maturity: [{ evidence: 'lab-bench', description: 'deployment mechanism cycled on the bench', where: 'test/TR-12' }],
|
|
}
|
|
|
|
const report = synthesize(concept)
|
|
console.log(formatSynthesis(concept))
|
|
```
|
|
|
|
The finding lines from that output (header, notes and detail lines omitted):
|
|
|
|
```
|
|
✗ CRITICAL 1 requirement(s) satisfied by no option: SYS-002 [NOT MET]
|
|
✗ CRITICAL No criterion tells the 2 options apart [NOT MET]
|
|
✗ CRITICAL N-2 is stated and no requirement covers it [NOT MET]
|
|
✗ CRITICAL SYS-002: invented [NOT MET]
|
|
✗ CRITICAL TRL 6 claimed, evidence supports TRL 3 [NOT MET]
|
|
✗ HIGH SYS-002: immeasurable [NOT MET]
|
|
◦ info SYS-001 traces to N-1 and is verifiable by analysis [MET]
|
|
```
|
|
|
|
The notes also give the maturation path to TRL 7: four steps starting from
|
|
the effective TRL 3, not one step from the claimed TRL 6.
|
|
|
|
The building blocks are exported too: `requirementIssues()`,
|
|
`unaddressedNeeds()`, `isMeasurable()`, `nonDiscriminating()`,
|
|
`isUndiscriminated()`, `dominatedOptions()`, `uncoveredRequirements()`,
|
|
`supportedTrl()`, `assessTrl()` and `maturationPath()`.
|
|
|
|
## Install
|
|
|
|
The package is published to the GitLab package registry, so point the
|
|
`@extant2000` scope there first:
|
|
|
|
```
|
|
npm config set @extant2000:registry https://gitlab.com/api/v4/packages/npm/
|
|
npm install @extant2000/mission-synth
|
|
```
|
|
|
|
## License
|
|
|
|
MIT. See [LICENSE](LICENSE).
|