Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2c0d450
#524: Add version to help text
redcatbear May 26, 2026
f40e5f7
#524: Added help requirements in system requirements and design.
redcatbear May 26, 2026
642fa0f
#524: Split help requirement and version requirement.
redcatbear May 26, 2026
411fc75
#524: Fixed tracing and tests for help commands.
redcatbear May 26, 2026
a2ee114
#524: Removed duplicate test.
redcatbear May 26, 2026
5c42b72
#524: Removed unnecessary newlines.
redcatbear May 26, 2026
fb5aa6d
#524: Fixed broken skill link.
redcatbear May 26, 2026
feb5369
#524: Improved general skill.
redcatbear May 26, 2026
009e950
#524: Added coverage for bad-weather scenarios in VersionProvider.
redcatbear May 26, 2026
e7d120d
#524: Fixed Sonar findings.
redcatbear May 26, 2026
648c847
#524: Removed the bad weather test cases, since SONAR did not see them.
redcatbear May 26, 2026
fda1fd9
#524: Logged exception message when version resource file can't be read.
redcatbear May 26, 2026
b19a715
Merge branch 'main' into feature/524_add-version-to-help-text
redcatbear May 27, 2026
44947b6
#504: Fixed findings in SKILL and renamed the file.
redcatbear May 27, 2026
1359bc8
#504: One section per tracing method.
redcatbear May 27, 2026
26ec873
#504: Added `.junie` to `.gitignore`.
redcatbear May 28, 2026
1390f30
#504: Fixed review findings in VersionProvider and corresponding tests.
redcatbear May 28, 2026
243d1ef
#504: Explained how the version gets into the resource file.
redcatbear May 29, 2026
0e7ff07
#524: Added ticket mention.
redcatbear May 30, 2026
d535f5c
#530: Add Mastodon link
redcatbear May 30, 2026
7536a82
Merge branch 'main' into documentation/530_add-mastodon-link
kaklakariada May 30, 2026
02c3c5d
Merge branch 'main' into documentation/530_add-mastodon-link
redcatbear May 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .agents/skills/openfasttrace-spec-driven-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Use these repository conventions unless the user explicitly says this project di

For OFT syntax, tracing behavior, selective tracing, and common error handling, read the upstream OpenFastTrace skill first:

`https://raw.githubusercontent.com/itsallcode/openfasttrace/refs/heads/main/skills/openfasttrace-skill/SKILL.md`
`https://raw.githubusercontent.com/itsallcode/openfasttrace/refs/heads/main/.agends/skills/openfasttrace/SKILL.md`

Do not restate OFT rules from memory when the upstream reference is available. Use it as the normative workflow for:

Expand All @@ -39,7 +39,7 @@ When the user gives you a new issue link, derive the work plan from:
4. the quality requirements document
5. the current code and tests

Do not jump straight to code. First determine whether the issue changes:
Do not jump straight to code. First, determine whether the issue changes:

- user-visible behavior
- traced requirements or scenarios
Expand Down
134 changes: 134 additions & 0 deletions .agents/skills/openfasttrace/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# OpenFastTrace (OFT) Skill

OpenFastTrace is a tool for requirement tracing across various artifacts (specifications, code, tests).

## Core Concepts

- **Specification Items**: Normative pieces of specification or coverage markers.
- **Artifact Types**: Dynamic and not hard-coded. New types exist automatically when used in a document.
- Common: `feat`, `req`, `arch`, `dsn`, `impl`, `utest`, `itest`, `stest`, `uman`, `oman`.
- **ID Syntax**: `type~name~revision` (e.g., `req~login-feature~1`).
- `name`: Hierarchical with dots (e.g., `ui.button.save`).
- `revision`: Integer used for versioning.
- Incrementing the revision breaks all incoming links (coverage and dependencies).
- This forces covering items to be updated and re-verified.
- **Keywords**:
- `Covers: <ID>`: Current item implements/details the target ID.
- `Needs: <types>`: Artifact types required to cover this item.
- `Status: <status>`: `draft`, `proposed`, `approved`.
- `Depends: <IDs>`: Defines dependencies (no effect on coverage).
- `Description: <text>`: Optional keyword to start description.
- `Rationale: <text>`, `Comment: <text>`.

## Syntax (Markdown)

```markdown
### Title
`req~id~1`
Description of the requirement.

Rationale: Why this is needed.

Covers: feat~parent~1

Needs: dsn, impl, utest
```

- **Forwarding**: `arch --> dsn : req~id~1` (delegates coverage without repeating).
- **Exclusion**: Use `<!-- oft:off -->` and `<!-- oft:on -->` to skip parsing.

## Tracing

Tracing can be performed via CLI, Maven, or Gradle.

### CLI Usage

General form: `oft <command> [options] <files/dirs>`

- **Commands**: `trace` (generate report), `convert` (export format), `help` (usage and version).
- **Options for `convert` and `trace`**:
- `-o, --output-format`: `plain`, `html`, `aspec` (XML).
- `-f, --output-file`: File path (default STDOUT).
- `-a, --wanted-artifact-types`: Filter by type (Partial Tracing).
- `-t, --wanted-tags`: Filter by tags (Partial Tracing). Use `_` for items without tags (e.g., `-t _,MyTag`).
- `-v, --report-verbosity`: `quiet`, `minimal`, `summary`, `failures`, `failure_summaries`, `failure_details` (default), `all`.
- `-i, --ignore-artifact-types`: Exclude types from import.

### Maven Integration

- **User Guide**: [openfasttrace-maven-plugin](https://github.com/itsallcode/openfasttrace-maven-plugin)

Add the `openfasttrace-maven-plugin` to your `pom.xml`:

```xml
<plugin>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-maven-plugin</artifactId>
<version>VERSION</version>
<executions>
<execution>
<goals><goal>trace</goal></goals>
</execution>
</executions>
<configuration>
<reportFormat>html</reportFormat>
<reportFile>target/site/tracing.html</reportFile>
</configuration>
</plugin>
```

- **Run**: `mvn openfasttrace:trace`

### Gradle Integration

- **User Guide**: [openfasttrace-gradle](https://github.com/itsallcode/openfasttrace-gradle)

Apply the plugin in `build.gradle`:

```gradle
plugins {
id "org.itsallcode.openfasttrace" version "VERSION"
}

openfasttrace {
reportFormat = "html"
}
```

- **Run**: `gradle trace`

### Partial Tracing & Filtering

Partial tracing allows teams to focus on specific layers of the traceability chain, reducing noise and build time.

**Example Scenario:**
- **Product Owner (PO)**: Writes system requirements (`req`). Traces `feat` → `req` to ensure all features are specified.
- **Architect**: Writes design specifications (`dsn`). Traces `feat` + `req` → `dsn` to ensure requirements are architecturally covered.
- **Developer**: Writes implementation (`impl`) and tests (`utest`). Traces `feat`+ … + `dsn` → `impl`, `utest` to verify complete implementation and testing of the design.

```text
[PO] --(feat)--> [req]
|
[Architect] -------+--(feat, req)--> [dsn]
|
[Developer] ---------------------------+--(feat, ..., dsn)--> [impl], [utest]
```

**Usage:**
- Filter by artifact types: `oft trace -a req,dsn <dir>`
- Filter by tags: `oft trace -t MyTag <dir>`
- Combine filters to focus on specific components or requirement levels.

## LLM Interaction Guidelines

- When identifying coverage, look for `impl~<ID>`, `utest~<ID>`, `itest~<ID>` and `stest~<ID>` in comments.
- Place markers at the narrowest possible scope (method/class).
- Ensure ID consistency across specifications and code.
- **Semantic Changes**: Increment the revision when the meaning of a requirement changes. This enforces a check of all covering items as their links become invalid.
- Verify changes by running tracing.

## Exit Codes

- `0`: Success.
- `1`: OFT error.
- `2`: Command line error.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ doc/**/*.html
/**/*.iml
/**/.project
.idea/
.junie/
*.iml
pom.xml.versionsBackup
.DS_Store
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Sonarcloud status:
* [➕ Changelog](doc/changes/changes.md)
* [📅 Upcoming Milestones](https://github.com/orgs/itsallcode/projects/3/views/3)
* [🗨️ Discussion Board](https://github.com/itsallcode/openfasttrace/discussions)
* [🐘 OpenFastTrace@mastodon.social](https://mastodon.social/@OpenFastTrace)
* [✨ OpenFastTrace Stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories)
* [ℹ️ About us](doc/about_us.md)

Expand Down
18 changes: 18 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@
<properties>
<project.build.outputTimestamp>${reproducible.build.timestamp}</project.build.outputTimestamp>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>version.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>version.properties</exclude>
</excludes>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.itsallcode.openfasttrace.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import java.util.logging.Logger;

/**
* Provides the version of OpenFastTrace from a resource file generated during
* build.
*/
public class VersionProvider
{
private static final Logger LOGGER = Logger.getLogger(VersionProvider.class.getName());
private static final String VERSION_PROPERTIES = "/version.properties";
private static final String UNKNOWN_VERSION = "(unknown version)";

/**
* Create a new instance of the {@link VersionProvider}.
*/
public VersionProvider()
{
// Default constructor
}

/**
* Loads the version number from the version.properties resource.
*
* @return the version string or "unknown" if it cannot be loaded.
*/
// [impl->dsn~cli.version~1]
public String getVersion()
{
final URL resource = getClass().getResource(VERSION_PROPERTIES);
if (resource == null)
{
return UNKNOWN_VERSION;
}
try (InputStream stream = resource.openStream())
{
final Properties properties = new Properties();
properties.load(stream);
return properties.getProperty("version", UNKNOWN_VERSION);
}
catch (final IOException exception)
{
LOGGER.warning("Error loading version from resource file: " + exception.getMessage());
return UNKNOWN_VERSION;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.itsallcode.openfasttrace.core.cli.commands;

import org.itsallcode.openfasttrace.core.VersionProvider;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;

/**
* Handler for printing command line usage.
*/
// [impl->dsn~cli.help~1]
public class HelpCommand implements Performable
{
/** The command line action for running this command. */
Expand All @@ -28,7 +31,8 @@ public HelpCommand(final boolean validUsage)
@SuppressWarnings("java:S106") // Using System.out by intention
public boolean run()
{
final String usage = loadResource("/usage.txt");
final String version = new VersionProvider().getVersion();
final String usage = loadResource("/usage.txt").replace("${version}", version);
System.out.println(usage);
return validUsage;
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/resources/usage.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
OpenFastTrace
OpenFastTrace ${version}

Usage:
oft command [option ...] [<input file or directory> ...]
Expand Down
1 change: 1 addition & 0 deletions core/src/main/resources/version.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version=${revision}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.itsallcode.openfasttrace.core;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import org.junit.jupiter.api.Test;

/**
* Integration test for {@link VersionProvider}.
* <p>
* Testing the bad weather cases requires using a custom classloader. But that
* makes the test coverage invisible. So we only test the happy path. The tests
* for the bad weather cases are too involved for testing a problem that is
* unlikely to occur with a static resource.
* </p>
*/
class VersionProviderIT
{
// [itest->dsn~cli.version~1]
@Test
void testLoadVersionFromProperties()
{
final String version = new VersionProvider().getVersion();
assertThat(version,
anyOf(
allOf(
not(containsStringIgnoringCase("unknown")),
not("${version}")
),
matchesPattern("\\d+\\.\\d+\\.\\d+")
)
);
}
}
10 changes: 5 additions & 5 deletions doc/about_us.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ ReqMgr ReqMgrNG ReqM/ReqM2 Allosaurus OFT OFT 1.0

```

OFT's roots go back to the year 2003 when it's first predecessor with the unimaginative name 'ReqMgr' (Requirement Manager) first saw the light of day at 3SOfT GmbH in Erlangen Tennenlohe (Germany). Being a software supplier for the automotive industry, 3SOFT had a need for requirement tracing to fulfill the strict rules for safety-critical software.
OFT's roots go back to the year 2003 when its first predecessor with the unimaginative name 'ReqMgr' (Requirement Manager) first saw the light of day at 3SOfT GmbH in Erlangen Tennenlohe (Germany). Being a software supplier for the automotive industry, 3SOFT had a need for requirement tracing to fulfill the strict rules for safety-critical software.

3SOFT was later acquired by the Finish Elektrobit group. [Bernd "Poldi" Haberstumpf](https://github.com/poldi2015) rewrote the complete requirement tracing code in the context of the [Autosar](https://www.autosar.org/) introduction to allow multi-level tracing in 2004. This new version was dubbed 'ReqMgrNG'. The introduction of the ASIL-D Autosar OS with microkernel eventually led to a stripped down version of 'ReqM2' which was missing a lot of functionality of the 'ReqMgrNG'.
3SOFT was later acquired by the Finish Elektrobit group. [Bernd "Poldi" Haberstumpf](https://github.com/poldi2015) rewrote the complete requirement tracing code in the context of the [Autosar](https://www.autosar.org/) introduction to allow multi-level tracing in 2004. This new version was dubbed 'ReqMgrNG'. The introduction of the ASIL-D Autosar OS with microkernel eventually led to a stripped-down version of 'ReqM2' which was missing a lot of functionality of the 'ReqMgrNG'.

In parallel another group of developers at Elektrobit worked on T-Reqs, a Java tool which did not see a lot of adoption.
In parallel, another group of developers at Elektrobit worked on T-Reqs, a Java tool which did not see a lot of adoption.

In even later projects performance became an issue, so ReqM2 and T-Reqs were both superseded by the much faster Allosaurus (yes, at this point in time everyone went full pun-mode).

While a lot faster, Allosaurus was somewhat clunky, and that was what started the development of OFT as a free software project. [Christoph Pirkl](https://github.com/kaklakariada/) and [Sebastian Bär](https://github.com/redcatbear) wrote OFT in their spare time while still working at Elekrobit with generous requirement engineering wisdom kindly supplied by Poldi.

[Thomas Fleischmann](https://github.com/quarterbit) was the main person to make OFT popular in the automotive industry, by tirelessly explaining its benefits to engineers and managers alike who were plagued by existing systems that were slow, proprietary and had terrible user experience.
[Thomas Fleischmann](https://github.com/quarterbit) was the main person to make OFT popular in the automotive industry, by tirelessly explaining its benefits to engineers and managers alike who were plagued by existing systems that were slow, proprietary, and had terrible user experience.

In automotive projects that span over a decade, it is vital to manage requirements in the same manner as the codebase. This approach enables diffing of requirements, implementing changes through PRs, and the easier merging of requirements between Start-of-Production (SOP) branches.

## Free and Open Source

One thing was clear for the four original founders of OFT. This time we wanted a broader community around our requirement tracing suite. And, since we were convinced that there is a need for requirement engineering in general and tracing in particular, we decided to start OpenFastTrace as an open source project on GitHub with the [first commit](https://github.com/itsallcode/openfasttrace/commit/f4e9167cedad499c168ab4bb9a4e20d762f33f8b) in December 2015. The made the first [release 0.1.0](https://github.com/itsallcode/openfasttrace/releases/tag/0.1.0) was in August 2017, and we reached the Minimum Viable Product (MVP) June 2018 with version [1.0.0](https://github.com/itsallcode/openfasttrace/releases/tag/1.0.0). OFT From then on OFT found its way into other industries outside the automotive world and also into the build toolchains of other open source projects. And that is the best thing we could ask for.
One thing was clear for the four original founders of OFT. This time we wanted a broader community around our requirement tracing suite. And, since we were convinced that there is a need for requirement engineering in general and tracing in particular, we decided to start OpenFastTrace as an open source project on GitHub with the [first commit](https://github.com/itsallcode/openfasttrace/commit/f4e9167cedad499c168ab4bb9a4e20d762f33f8b) in December 2015. The made the first [release 0.1.0](https://github.com/itsallcode/openfasttrace/releases/tag/0.1.0) was in August 2017, and we reached the Minimum Viable Product (MVP) in June 2018 with version [1.0.0](https://github.com/itsallcode/openfasttrace/releases/tag/1.0.0). OFT From then on OFT found its way into other industries outside the automotive world and also into the build toolchains of other open source projects. And that is the best thing we could ask for.
9 changes: 6 additions & 3 deletions doc/changes/changes_4.5.0.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# OpenFastTrace 4.4.0, released 2026-05-??

Code name: ???
Code name: 10 years of OFT

## Summary

In this release we added the option `-h` / `--help` to the command line.
OpenFastTrace just turned ten counting from the first release. We are on Mastodon now: https://mastodon.social/@OpenFastTrace

In this release we added the option `-h` / `--help` to the command line. Also, the help message now prints the version of OpenFastTrace.

We also refactored the tests around the CLI starter to improve readability and maintainability and made getting the test coverage easier.

Expand All @@ -15,4 +17,5 @@ When no importer factory is found for a given file format, the importer factory
## Features

* #503: Added `-h` / `--help` to the command line.
* #506: Exception when no importer was found.
* #506: Exception when no importer was found.
* #524: Added version number to help text.
26 changes: 26 additions & 0 deletions doc/spec/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,32 @@ Needs: impl, itest

### Common

#### CLI Help
`dsn~cli.help~1`

The CLI provides a help command and flags (`help`, `-h`, `--help`) that display a short help text.

Covers:

* [`req~cli.help~1`](system_requirements.md#cli-help)

Needs: impl, itest

#### CLI Version
`dsn~cli.version~1`

The CLI provides the current version of OpenFastTrace read from the resource file `version.properties` that is created druing the build from the property `revision` in the core POM.

Rationale:

This makes the `revision` the single source of truth for the version of OpenFastTrace and avoids having to keep manually maintained copies of the version information.

Covers:

* [`req~cli.version~1`](system_requirements.md#cli-version)

Needs: impl, itest

#### Input File Selection
`dsn~cli.input-file-selection~1`

Expand Down
Loading
Loading