Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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`
Comment thread
redcatbear marked this conversation as resolved.

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.
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>
Comment on lines +25 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the file included and excluded?

Suggested change
<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";

/**
* 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());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also log stack trace?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that is necessary in this case. It's a static resource anyway. Not much that can go wrong.

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}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OpenFastTrace ${version}
OpenFastTrace version ${version}

Avoid confusion in case the version is UNKNOWN


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,29 @@
package org.itsallcode.openfasttrace.core;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertAll;

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.
Comment thread
redcatbear marked this conversation as resolved.
* </p>
*/
class VersionProviderIT
{
// [itest->dsn~cli.version~1]
@Test
void testLoadVersionFromProperties()
{
final String version = new VersionProvider().getVersion();
assertAll(() -> assertThat(version, is(not("unknown"))),
() -> assertThat(version, is(not("${version}"))));
Comment on lines +26 to +27
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the unknown value case insensitive, add an assertion using a regex \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.
2 changes: 1 addition & 1 deletion doc/changes/changes_4.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Code name: ???

## Summary

In this release we added the option `-h` / `--help` to the command line.
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 Down
22 changes: 22 additions & 0 deletions doc/spec/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,28 @@ 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`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading from a resource file is an implementation detail. If you want to be so specific, please also describe how the version gets into this file ;)


Covers:

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

Needs: impl, itest

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

Expand Down
24 changes: 23 additions & 1 deletion doc/spec/system_requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,29 @@ Covers:
Needs: dsn

#### Common


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

`help`, `-h` and `--help` show a short help text with command line usage.

Covers:

* [feat~command-line-interface~1](#command-line-interface)

Needs: dsn

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

`help`, `-h` and `--help` show the version of OFT.

Covers:

* [feat~command-line-interface~1](#command-line-interface)

Needs: dsn

##### Input Selection
`req~cli.input-selection~1`

Expand Down
Loading
Loading