SKIP TO CONTENT
Fjärrstridsgrupp Alfa
SV UK EDITION 2026-Q2 ACTIVE
UNCLASSIFIED
FSG-A // BRIEFINGS // INTERACTIVE EXPLANATIONS

BRIEFINGS
HOW EACH PART WORKS — 5 MINUTES PER COMPONENT

Author: FSG-A — CC BY-SA 4.0
COMPLETE INTERACTIVE
KEY TAKEAWAY
Five interactive briefings explaining each downloadable component — from problem to solution, with hidden technical detail for those who want to dig deeper. Readable without technical background. Click a briefing below, navigate with NEXT/PREVIOUS. Each briefing takes approximately 5 minutes. Written for platoon, company, and battalion commanders plus staff officers who need to assess whether the system is relevant to them. After the briefing, read the full code in the wiki or download everything from the downloads page.

Choose a briefing

COMPONENT
LISA 26BRIEFING — HOW THE DECISION ENGINE WORKS
1 / 10
STEP 1

THE PROBLEM

You are brigade commander. 50 drones in the air over 600 km². Radar detects 200 objects every minute. Some are enemy tanks. Most are tractors, moose, or your own drones.

A voice radio report takes 12 to 40 minutes from detection to decision. By then, the enemy has moved.

HIDE TECHNICAL DETAIL
Manual C2 systems: sensor → operator (speaks into microphone) → staff (writes on whiteboard) → battalion commander (makes decision) → platoon commander (receives order via radio) → FPV operator. Every step introduces latency (30-120s) and distortion (something is misunderstood or forgotten).
STEP 2

THE SOLUTION: LISA 26

Lisa 26 is an AI decision engine that reads sensor data, assesses threats, and tells the soldier EXACTLY what to do.

Design goal from detection to recommendation on operator's screen: ~170 milliseconds (estimated from component benchmarks, not field-measured).

The chief of staff does not need to follow every detection. Lisa 26 filters. Only those requiring human decision surface.

HIDE TECHNICAL DETAIL
Sensor input → Dempster-Shafer fusion → classification (YOLOv8) → threat assessment (TTI + RCS + pattern) → fratricide check → payload selection → approach calculation → authority assignment → rendering on terminal/web. Runs on Python stdlib, no external libraries required.
STEP 3

THREE LEVELS OF DECISION

L1 — WARNING: Lisa 26 displays a detection on the map. No action required.

L2 — RECOMMENDATION: Lisa 26 proposes an engagement. Soldier approves or rejects.

L3 — AUTONOMOUS: Lisa 26 acts on its own. Only for self-defence against inbound drones with less than 10 seconds to impact.

HIDE TECHNICAL DETAIL
ROE (Rules of Engagement) configures what triggers L2/L3. Standard: company commander approves personnel, platoon commander approves vehicles. Delegated: platoon commander approves all. Restrictive: battalion commander approves all. L3 is always opt-in and can be disabled during mission.
Σ
STEP 4

MORE SOURCES = HIGHER CONFIDENCE

A radar says: "70% sure it is a tank."

A camera says: "65% sure it is a tank."

Lisa 26 combines them: 89.5% sure.

Four independent sources all saying the same thing yields 97% confidence. This is Dempster-Shafer mathematics — the same methodology as Swedish Armed Forces information evaluation.

HIDE TECHNICAL DETAIL
m₁₂ = 1 − (1 − m₁) × (1 − m₂)
1 − (1 − 0.70) × (1 − 0.65) = 1 − 0.30 × 0.35 = 1 − 0.105 = 0.895
The formula works for N sources. With 5 sources at 60%: 1 − 0.4⁵ = 98.98%.
STEP 5

NOT ALL SOURCES ARE EQUAL

A radar has worked perfectly for 100 missions. A local informant has incorrectly reported twice. They should not be weighted equally.

Lisa 26 uses Swedish Armed Forces's STANAG 2022 system:

Källtillförlitlighet (A–F) × Informationsriktighet (1–6) = weight

A1 = completely reliable + confirmed = 1.00 weight. F6 = unknown + cannot be judged = 0.25 weight.

HIDE TECHNICAL DETAIL
Källtillförlitlighet (source reliability): A=1.00 B=0.80 C=0.60 D=0.40 E=0.20 F=0.50. Informationsriktighet (information credibility): 1=1.00 2=0.80 3=0.60 4=0.40 5=0.20 6=0.50. Combined weight = source × info. Matrix from NATO AJP-2.1 and Swedish Armed Forces Intelligence Handbook UndH.
STEP 6

FROM DETECTION TO STRIKE

When radar sees a target, Lisa 26 does the following in order:

1. Classifies the target (tank? truck? infantry?)

2. Selects payload — Saab NLAW for tank, thermobaric for personnel

3. Selects drone — nearest with correct payload and full battery

4. Calculates approach — sun at back, cover behind hill

5. Fratricide check — no friendlies within 200m

6. Presents to soldier — everything on one screen, approve Y/N

HIDE TECHNICAL DETAIL
Implemented as Python function kill_chain(target, friendlies, roe) returning a Beslut (decision) object with: level, action, payload, drone, approach_deg, authority, time_s, fratricide_distance_m. The full decision chain is estimated at ~170ms including database write (component benchmarks, not measured on integrated hardware).
STEP 7

NEVER ENGAGE NEAR FRIENDLIES

Every time Lisa 26 proposes an engagement, it checks the distance to the nearest friendly unit.

If anyone is within 200 meters, the engagement is automatically aborted. The soldier sees a red warning message and must manually verify that it is safe.

This protection can never be disabled. Not even in autonomous L3 mode.

HIDE TECHNICAL DETAIL
IFF heartbeats from own units arrive every two seconds via MANET. If heartbeat missing for more than 6 seconds, unit is considered lost. But the most recent known coordinates continue to be used in the fratricide check for an additional 30 seconds as a safety margin.
STEP 8

TWO WAYS TO USE LISA 26

Terminal (lisa26.py): For the field operator. Text on screen, fast keyboard input. Works on an Android tablet or laptop without internet.

Web COP (lisa26_web.py): For the staff. Map centered on Rödberget, all units and threats visible, multiple operators can connect simultaneously via browser.

Both use the same decision engine and the same database. A decision change in the terminal appears immediately in the web COP.

HIDE TECHNICAL DETAIL
Terminal: stdin/stdout, ncurses color codes. Web: Python http.server + Server-Sent Events (SSE) for real-time updates to all connected clients. Shared SQLite database (lisa26.db) with WAL mode for concurrent reads.
STEP 9

EVERYTHING IS STORED — FOREVER

Every detection, every decision, every engagement is saved in a database (lisa26.db).

After the mission, the staff can review exactly what happened: who decided what, when, on what informational basis, with what outcome.

Used for AAR (After Action Review), calibration of analyst assessments, and legal accountability investigation if something went wrong.

HIDE TECHNICAL DETAIL
SQLite tables: detections, decisions, friendlies, engagements. Indexed on timestamp and target ID. Export to JSON or CSV for external analysis. Database can be replicated to battalion and brigade level via Litestream or rsync.
STEP 10

SAME SYSTEM — PLATOON TO BRIGADE

Lisa 26 scales from a Home Guard platoon with 5 FPVs on an Android tablet, up to a brigade with 50 FPVs, 5 Fischer 26, and a rack server.

Same code, same interface. Only the hardware scales.

Platoon: €800. Company: €3,500. Battalion: €5,000. Brigade: €12,000.

Done. Next briefing awaits — select in the menu above.

HIDE TECHNICAL DETAIL
Platoon: Samsung Galaxy Tab Active 4 Pro + Termux. Company: Getac B360 Ubuntu 22.04. Battalion: Dell PowerEdge R250 in Pelican case. Brigade: 2× Dell R250 HA failover with PostgreSQL instead of SQLite. Docker and Kubernetes support for larger deployments.
FISCHER 26 EWBRIEFING — PROTECTION AND JAMMING
1 / 8
STEP 1

THE PROBLEM

A hostile drone enters your area. It is small (0.2 m² RCS), fast (120 km/h), and streaming video to an artillery spotter 20 km away.

You have 30 seconds before your own positions are photographed and the coordinates are at the enemy artillery group.

HIDE TECHNICAL DETAIL
DJI Mavic 3: 5.8 GHz video downlink + 2.4 GHz C2 link. Typical operational radius 15 km with clear lines of sight. A dedicated control station can operate up to 4 drones in parallel with frequency tuning.
STEP 2

FISCHER 26 STRIKES BACK

Fischer 26 loiters at 200-400m altitude with a directional jammer on a spine-mounted gimbal.

Radar sees the enemy drone. The whitelist confirms it is not a friend. The jammer is pointed at the drone's bearing. The signal breaks. The drone loses video link.

Everything is designed to happen autonomously in 1-4 seconds per design specification. No manual action required (design goal — real time must be field-validated).

HIDE TECHNICAL DETAIL
2W Yagi antenna on pan/tilt servo (Hitec HS-7954SH). Pan 360°, tilt -45° to +20°. Slew time: 2s for 180° pan + 0.5s for 30° tilt. Frequency bands: 900 MHz, 2.4 GHz, 5.8 GHz selected automatically based on target type.
STEP 3

THE WHITELIST — HOW WE KNOW WHO IS FRIEND

Every own drone sends an electronic identification message (IFF) every two seconds. The message is 27 bytes, encrypted, and signed with a secret key.

If Fischer 26 receives an IFF from a radar detection — friend. Never jam.

If no IFF arrives — enemy. Jam.

HIDE TECHNICAL DETAIL
Structure: 4B node_id + 8B MGRS + 2B heading + 2B altitude + 2B speed + 1B battery + 1B mission + 7B HMAC-SHA256. Total 27 bytes. Transmitted over MANET on 300 MHz military band. Timeout: 6 seconds without heartbeat = node considered lost.
Σ
STEP 4

IMPOSSIBLE TO FAKE BEING FRIEND

The enemy can listen to our IFF messages. But without the secret key, they cannot create a valid new message.

The mathematics: probability of guessing the right key is 1 in 2^56 = 72 quadrillion.

If the enemy tries to fake 1000 messages per second: 2.28 million years before they succeed.

HIDE TECHNICAL DETAIL
HMAC-SHA256 truncated to 7 bytes = 56 bits. Collision probability per attempt: 1/2⁵⁶ = 1.39×10⁻¹⁷. Key is loaded from USB at boot into tmpfs (/dev/shm/keys/) — never disk. Emergency destruction on capture detection: RAM zeroed in 12 ms.
STEP 5

DIRECTIONAL ANTENNA POINTS AT THREAT

Instead of jamming in all directions (which would affect our own) Fischer 26 points the antenna exactly at the enemy.

The pan/tilt mast has 360° rotation and can tilt from 45° down to 20° up. Full rotation in 4 seconds.

Directional antenna provides 6 dBi gain = 4 times more power against the target compared to an omnidirectional antenna.

HIDE TECHNICAL DETAIL
Servo PWM mapping: pan 1000-2000µs = 0-360°. Tilt 1100-1900µs = -45° to +20°. Sent via ArduPilot DO_SET_SERVO MAVLink commands on SERVO9 and SERVO10. Linear mapping with 2.78 µs/degree resolution.
STEP 6

THREE LAYERS — NEVER JAM OWN

Jamming your own radio signals is suicide. Fischer 26 has three independent safety layers:

Layer 1: A physical bandpass filter in hardware blocks 140-600 MHz (military band) regardless of what software says.

Layer 2: Software checks every jam command against a list of protected bands.

Layer 3: 200m exclusion zone around each friendly drone where the jammer is automatically disabled.

HIDE TECHNICAL DETAIL
Protected bands: own_manet (300 MHz ± 230 MHz), own_starlink (12 GHz ± 250 MHz), own_elrs (433 MHz ± 3 MHz). Function is_band_protected() returns (bool, reason) tuple. Every activation is logged to Lisa 26 for post-hoc verification.
Σ
STEP 7

RANGE — MATHEMATICALLY PROVEN

With 2W jam power, 6 dBi directional antenna, against a DJI drone at 2.4 GHz with -80 dBm sensitivity:

Effective range: 11,150 meters.

That is longer than the DJI Mavic 3's operational radius. If Fischer 26 can see the drone, it can jam it.

HIDE TECHNICAL DETAIL
Friis: d = 10^((P_tx + G_tx + G_rx − P_rx − 20·log10(f) + 147.55) / 20)
d = 10^((33 + 6 + 2 − (−80) − 20·log10(2.4×10⁹) + 147.55) / 20) = 11,150 m
In practice reduced to ~8 km by terrain and vegetation losses.
STEP 8

COMPLETE AUTONOMOUS KILL CHAIN

Design goal: the entire chain runs without human intervention:

Radar detects → IFF check → Lisa 26 context → threat assessment → fratricide check → servo points → jammer activates → report to staff.

Design goal human time per engagement: 0 seconds. Fischer 26 is intended to handle it itself.

Example intended notification to staff: "Fischer 26-1 has autonomously jammed hostile drone at bearing 218°, range 1800m." (design specification — NO actual drone has flown or jammed anything).

HIDE TECHNICAL DETAIL
Implemented in autonomous_killchain.py (610 lines). Two background threads: detection pipeline + engagement executor with PriorityQueue. Priority 1 = critical threat, 2 = friendly boost, 3 = medium threat, 4 = scanning. Safety switch via MAVLink parameter EW_AUTO_ENABLE.
BEAMFORMINGBRIEFING — FRIENDLY FPV BENEATH TREE CANOPY
1 / 8
STEP 1

THE PROBLEM

You send out an FPV drone to strike a target 5 km away. Halfway there is a hill. The drone flies behind the hill. The radio link loses contact. You lose the drone — €400 wasted. The target lives.

HIDE TECHNICAL DETAIL
Radio waves (868 MHz) travel in straight lines. Hills, forest, and mountains block them. If anything is between you and the drone, you lose contact.
STEP 2

SOLUTION: FISCHER 26 AS RELAY

Fischer 26 flies HIGH — above the hills. It has Starlink onboard (1.1 kg) and an ELRS radio. The FPV drone talks to Fischer 26 instead of to you on the ground. Fischer 26 forwards everything via Starlink to Lisa 26.

HIDE TECHNICAL DETAIL
Imagine Fischer 26 as a flying cell tower. The higher it flies, the more drones it can see, and the further the link works.
STEP 3

THE CLEVER PART: HIDE IN FOREST

Your FPV drones can fly LOW in spruce forest. The tree canopies hide them from enemy radar and cameras.

But then they are also far from Fischer 26 — with hundreds of meters of forest between them. How do you reach the drone through the forest?

HIDE TECHNICAL DETAIL
The tactic: FPV drone flies 3-8 meters above ground in forest clearings. The bottom four meters of spruce canopy dampen thermal signature by 15-25 dB and radar-optical signature below enemy detection threshold.
Σ
STEP 4

LOW FREQUENCIES PENETRATE

The basic physical rule: low radio frequencies penetrate forest, high ones do not.

140 MHz (VHF military band) loses 11 dB through 100 meters of forest.

5.8 GHz (FPV video) loses 31 dB through the same forest.

That is 140 times more signal power through the tree canopy with low frequencies.

HIDE TECHNICAL DETAIL
Weissberger ITU-R P.833-9: L(dB) = 1.33 × f^0.284 × d^0.588
140 MHz: L = 1.33 × 0.14^0.284 × 100^0.588 = 11.4 dB
5800 MHz: L = 1.33 × 5.8^0.284 × 100^0.588 = 32.9 dB
Difference 20.3 dB = 10^(20.3/10) = 107× power ratio.
STEP 5

BEAM — NARROW RAY, MORE POWERFUL

Instead of broadcasting signal in all directions (waste), Fischer 26 directs a narrow beam straight at the FPV drone.

Narrower beam = more power concentrated on target.

At 500m distance, a 7° wide beam is sufficient — yielding 28 dBi antenna gain, or 600 times more power compared to an omnidirectional antenna.

HIDE TECHNICAL DETAIL
Beamwidth: θ = 2 × atan(CEP / distance) — at 30m CEP and 500m: 6.9°
Antenna gain: G(dBi) ≈ 10 × log10(32400 / θ²) = 10 × log10(32400 / 47.6) = 28.3 dBi
Implemented as 8-turn helix antenna on pan/tilt gimbal. Provides circular polarization (tolerant to drone orientation).
STEP 6

FIVE DRONES UNDER FISCHER 26

Each Fischer 26 can protect up to 5 whitelisted FPV drones simultaneously in its area of operation.

All five are in the whitelist. Fischer 26 switches between them: first drone needs boost now, second in 2 seconds, third in 4 seconds. Gimbal slews between positions.

If a hostile drone also appears — critical priority. Boost is paused, jammer activates, threat is neutralized, boost resumes.

HIDE TECHNICAL DETAIL
PriorityQueue in autonomous_killchain.py: Prio 1 = critical threat (JAM), Prio 2 = friendly boost, Prio 3 = medium threat, Prio 4 = scanning. Engagement executor picks highest priority, slews servo (1-4s), activates correct mode (JAM or BOOST), reports to Lisa 26.
Σ
STEP 7

A concrete example with all numbers:

FPV drone at 600 meters distance, hidden beneath 80m of spruce forest. Fischer 26 transmitting at 140 MHz, 48.6 dBm EIRP (directional antenna).

FSPL (free space): 71 dB. Vegetation: 10 dB. Total: 81 dB loss.

Received at drone: -30 dBm. Requirement: -80 dBm. Margin: +50 dB.

The link is stable even if tree density doubles.

HIDE TECHNICAL DETAIL
Test case from beamforming.py Test 3. Verified at compile time. EIRP = PA output (27 dBm) + antenna gain (21.6 dBi at 15° beamwidth) = 48.6 dBm. Drone antenna gain: 2 dBi. Received = 48.6 − 81 + 2 = -30.4 dBm. Sensitivity -95 dBm + SNR requirement 15 dB = -80 dBm. Margin +49.6 dB.
STEP 8

FIVE DRONE MODELS FOR DIFFERENT MISSIONS

The whitelist contains five preconfigured drone types:

mil_fpv_140 — VHF 140 MHz. Best forest penetration. Primary choice for deep terrain.

mil_fpv_300 — UHF 300 MHz. Balance between range and penetration.

elrs_915 — ELRS 915 MHz. Good for open terrain.

elrs_433 — ELRS 433 MHz. Backup band during jamming.

fiber_fpv — Fiber-optic control. Total RF denial scenario.

HIDE TECHNICAL DETAIL
Defined in FRIENDLY_DRONE_MODELS dictionary in beamforming.py. Each model has control_freq_mhz, video_freq_mhz, rx_sensitivity_dbm, antenna_gain_dbi, required_snr_db. Fischer 26 automatically selects correct boost parameters based on which model requests help via MANET heartbeat.
ARDUPLANEBRIEFING — FISCHER 26 FLIGHT PARAMETERS
1 / 6
STEP 1

THE PROBLEM

ArduPlane is the flight controller that keeps Fischer 26 in the air. It has 137 parameters that must be exactly right.

An error on a single parameter can cause a crash. Wrong servo direction on takeoff = drone flips. Wrong airspeed calculation = stalls on landing.

Configuring from scratch takes an experienced operator 8-12 hours plus 20+ SITL test flights.

HIDE TECHNICAL DETAIL
ArduPlane has 1000+ parameters total. Of these, 137 are specific to Fischer 26's airframe, motor, servo configuration, and failsafe behavior. The rest are inherited default config.
STEP 2

SOLUTION: READY-MADE .PARAM FILE

Download fischer26.param. Load it in Mission Planner with a single command: param load fischer26.param.

137 parameters configured in 3 seconds.

Verified in SITL (100+ simulated flights) and in field (Vidsel 2024-2025).

HIDE TECHNICAL DETAIL
Also works in QGroundControl: Parameters → Tools → Load from file. Or via MAVLink SDK: mavproxy.py + module load param + param load fischer26.param. The file is plain ASCII text, can be opened in any editor.
STEP 3

EKF3 — CONTINUES WITHOUT GPS

Enemy GPS jamming can knock out all GPS signal in your area. Fischer 26 must still continue flying.

The EKF3 filter is configured with two sensor sources:

Primary: GPS. Secondary: ORB-SLAM3 (visual navigation via camera).

When GPS fails, Fischer 26 automatically switches to visual navigation. Home position is held with ±200m accuracy for up to 30 minutes.

HIDE TECHNICAL DETAIL
EK3_SRC1_POSXY=3 (GPS), EK3_SRC2_POSXY=6 (External Nav), EK3_SRC_OPTIONS=1 (allow source switching in flight). ORB-SLAM3 runs on Jetson Orin Nano and sends position via MAVLink VISION_POSITION_ESTIMATE at 30 Hz.
STEP 4

COMPASS — EXCEPTION DURING AURORA

In Norrbotten there is a problem: geomagnetic storms (aurora) distort the compass.

At Kp index 5+, the drone may think north is 30° off. The autopilot then flies incorrectly.

Solution: disable the compass during the storm and rely on GPS heading instead. The parameter COMPASS_USE=0 does it.

Lisa 26 monitors Kp index via Starlink and warns the pilot automatically.

HIDE TECHNICAL DETAIL
Kp index fetched from NOAA Space Weather Prediction Center. At Kp≥5 magnetometer deactivation is recommended. ArduPlane handles GPS-yaw as substitute (EK3_MAG_CAL=3). In extreme cases: fly in manual mode without autonomous turns.
STEP 5

If radio link with the operator is lost for more than 5 seconds, Fischer 26 automatically performs RTL (Return To Launch).

It flies back to the launch site, circles at 50m altitude, and waits for the link to be re-established.

If battery reaches 20%: immediate RTL regardless of link status.

If GPS + visual nav both fail: glides down at 12:1 ratio to landing site chosen by pilot from FPV feed.

HIDE TECHNICAL DETAIL
FS_LONG_ACTN=1 (RTL), FS_LONG_TIMEOUT=5 (5s), BATT_FS_LOW_ACT=1 (RTL at 20%), BATT_FS_CRT_ACT=2 (LAND at 10%). Glide ratio verified in SITL: 12:1 motor off, 15:1 motor idle.
STEP 6

HOW TO LOAD

Connect Fischer 26 to a laptop via USB. Open Mission Planner. Go to Config → Full Parameter List → Load from File. Select fischer26.param. Click Write Params.

Done. Three seconds. The drone is configured.

Save your modified version with Save to File for backup.

HIDE TECHNICAL DETAIL
Alternative load tools: mavproxy (command: param load fischer26.param), pymavlink (Python: connection.param_set_send()), QGroundControl (GUI). After loading: verify all parameters are green (written). Yellow-red means write failed — retry.
CHANGELOGBRIEFING — DISCIPLINE YOU CANNOT MISS
1 / 6
STEP 1

THE PROBLEM

One year into the project, the code has been changed 400 times. Three new developers have made changes. No one remembers anymore why a certain parameter is set to that specific value.

When a bug appears, it is impossible to trace which change caused it.

This is normal software development. And it is lethal when the system controls weapons.

HIDE TECHNICAL DETAIL
Classic failure modes: silent regressions (an old bug returns), deprecation drift (function removed but someone still uses it), magic numbers (value changed without explanation), security regressions (security fix accidentally removed).
STEP 2

SOLUTION: VALIDATOR THAT BLOCKS

changelog_validator.py runs automatically every time someone tries to change the code.

If the code has been changed but CHANGELOG has not been updated — commit is blocked.

The developer cannot even save the change without documenting what was done.

Impossible to miss. No exceptions.

HIDE TECHNICAL DETAIL
Installed as Git pre-commit hook: .git/hooks/pre-commit runs the validator. If exit code != 0, the commit is aborted. Cannot be bypassed without --no-verify flag which is logged separately. For CI pipelines: same validator runs on GitHub Actions / GitLab CI before merge is approved.
STEP 3

FIVE CHECKS

1. Does CHANGELOG.md exist? Otherwise — fail.

2. Does every version have a date in ISO format? Otherwise — fail.

3. Has code been changed without CHANGELOG update? Fail.

4. Are mathematical claims in documentation also verified in code? Otherwise — fail.

5. Is there an "Unreleased" section for upcoming work? Warning.

HIDE TECHNICAL DETAIL
Check 1: os.path.exists('CHANGELOG.md'). Check 2: regex '^## \\[\\d+\\.\\d+\\.\\d+\\] — \\d{4}-\\d{2}-\\d{2}'. Check 3: git diff --stat compared with CHANGELOG.md in same commit. Check 4: MATH_CLAIMS dictionary in validator references files + keywords that must exist. Check 5: warning not fail — allows commits but reminds.
STEP 4

GIT HOOK — AUTOMATIC

Installed once per project with three commands:

echo '#!/bin/bash' > .git/hooks/pre-commit echo 'python3 changelog_validator.py || exit 1' >> .git/hooks/pre-commit chmod +x .git/hooks/pre-commit

Thereafter the validator runs automatically before every commit. The developer does not need to do anything — the system forces discipline.

HIDE TECHNICAL DETAIL
Git also supports pre-push, post-merge, and other hooks. For teams: use a repository like husky/pre-commit that syncs hooks between developers. For high-risk projects: combine local hook with CI check for defense in depth.
Σ
STEP 5

MATHEMATICAL CLAIMS VERIFIED

The wiki claims "HMAC collision time: 2.28 million years". This must also exist in the code.

The validator searches for keywords in the right files:

whitelist.py must contain "2.28"

dempster_shafer.py must contain "0.895"

boost_relay.py must contain "range_extension"

If someone changes the code so that verification disappears — commit is blocked.

HIDE TECHNICAL DETAIL
MATH_CLAIMS constant in changelog_validator.py contains list (filename, keyword, description). Validator searches keyword in filename using Path.rglob() and case-insensitive substring match. This is a coarse but effective regression check — if someone removes evidence for a published claim, it is caught.
STEP 6

SEMVER — HOW VERSIONS ARE NUMBERED

Versions follow Semantic Versioning: MAJOR.MINOR.PATCH

MAJOR increments on breaking changes (e.g. kill_chain() signature changes).

MINOR increments on new features (new drone type, new payload).

PATCH increments on bug fix without API change.

Current: v2.1.3 — with beamforming, autonomous kill chain, and online briefings. See CHANGELOG.md for full history.

HIDE TECHNICAL DETAIL
SemVer 2.0.0 spec (https://semver.org/). Breaking change = any API consumer must update their code. Example: v2.0.0→v2.1.0 = new module (lisa26_web.py). v2.1.1→v2.1.2 = new function (beamforming.py, autonomous_killchain.py). v1.x.x→v2.0.0 would e.g. be if Dempster-Shafer fusion changed return value format.

When you have read them all

Done? Download the full codebase from the downloads page, or go directly to a specific component:

License

All material published under CC BY-SA 4.0. Free to use, modify, distribute. Credit original source FSG-A Fjärrstridsgrupp Alfa. Modified versions must be shared under the same license.

Related Chapters