Files
mission-synth/README.md
T
Paul HittandClaude Opus 5.5 cd777f50aa Publish to the GitLab package registry on version tags
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>
2026-09-28 16:42:02 -04:00

6.4 KiB

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

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.