Metadata-Version: 2.4
Name: syntagmax
Version: 2026.7.30
Summary: Git-Based Requirements Management System
Project-URL: Homepage, https://github.com/flyvercity/syntagmax
Project-URL: Repository, https://github.com/flyvercity/syntagmax
Project-URL: Issues, https://github.com/flyvercity/syntagmax/issues
Project-URL: Changelog, https://github.com/flyvercity/syntagmax/blob/main/CHANGELOG.md
Author-email: Flyvercity <boris@flyver.city>
License-Expression: MIT
License-File: LICENSE
Keywords: engineering,git,requirements,requirements-engineering,requirements-management,traceability
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Documentation
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Topic :: Text Processing :: Markup :: Markdown
Requires-Python: >=3.13
Requires-Dist: babel>=2.14
Requires-Dist: click>=8.1.8
Requires-Dist: gitpython>=3.1.44
Requires-Dist: jinja2>=3.1
Requires-Dist: lark>=1.3.1
Requires-Dist: mcp[cli]>=1.16.0
Requires-Dist: polars>=1.36.1
Requires-Dist: pydantic>=2.11.10
Requires-Dist: python-benedict[parse,toml,yaml]>=0.35.0
Requires-Dist: pyyaml>=6.0.2
Requires-Dist: requests>=2.34.2
Requires-Dist: rich>=13.9.4
Requires-Dist: ruamel-yaml>=0.18.0
Requires-Dist: uvicorn>=0.30.0
Provides-Extra: bedrock
Requires-Dist: boto3>=1.34.0; extra == 'bedrock'
Provides-Extra: images
Requires-Dist: pillow>=10.0.0; extra == 'images'
Description-Content-Type: text/markdown

# Syntagmax - Git-Based Requirements Management System

Fully git-friendly lightweight requirements management system with tracing model verification, change detection, and propagation.

## Quick Demo (Development Environment)

Run example analysis with:

```bash
uv run syntagmax --render-tree --cwd ./example/obsidian-driver/ analyze
```

Run example publishing with:

```bash
uv run syntagmax --cwd ./example/obsidian-driver publish .syntagmax/reports/output.md
```

Run example tracing export with:

```bash
uv run syntagmax --cwd ./example/obsidian-driver trace --child REQ --parent SYS
```

## Getting Started

To initialize a new Syntagmax project in the current directory:

```bash
syntagmax init
```

This command creates a `.syntagmax` directory with:
- `config.toml`: A template configuration file with common options.
- `project.syntagmax`: A basic metamodel definition to get you started.

## Configuration

Syntagmax uses a TOML configuration file (default `.syntagmax/config.toml`). Key sections include:

- `[[input]]` — input source definitions (driver, artifact type, filters)
- `publish` — global publish config file path (relative to config file directory)
- `[metrics]` — metrics collection settings
- `[impact]` — impact analysis settings
- `[metamodel]` — metamodel file path
- `[ai]` — AI provider and model settings
- `[trace]` — trace export plugin configuration

For details on how all these paths are resolved relative to the project configuration file, see the [Paths Reference](docs/reference/paths.md).

```toml
base = ".."
log_level = "info"

[[input]]
name = "requirements"
dir = "requirements/REQS"
driver = "obsidian"

[metrics]
enabled = true

[metamodel]
filename = "project.syntagmax"

[ai]
provider = "anthropic"
model = "claude-sonnet-4-6"
```

For the full schema, input source options, marked fragments, and AI provider settings, see [docs/reference/configuration.md](docs/reference/configuration.md). Detailed path resolution rules are described in [docs/reference/paths.md](docs/reference/paths.md).

For detailed Obsidian driver extraction rules, block termination behavior, and fragment marker processing, see [docs/reference/obsidian.md](docs/reference/obsidian.md).

## Git Integration

Syntagmax automatically extracts revision history for each artifact using Git. This provides traceability and helps track changes over time.

### Revision Descriptors

Each artifact is attached with a set of revisions. A revision includes:
- **Short Hash**: The 7-character commit hash.
- **Timestamp**: Date and time of the commit.
- **Author**: Email of the commit author.

### Extraction Logic

- **Text-based artifacts** (e.g., source code sections, Obsidian requirements): Syntagmax uses `git blame` to identify all commits that affected the specific lines where the artifact is defined.
- **Sidecar artifacts**: Syntagmax identifies the last commit that affected the primary file (e.g., an image) and all commits that affected the sidecar metadata file.

### Disabling Git Integration

If you want to skip git history extraction (e.g., if you are not in a git repository or want to speed up analysis), use the `--no-git` flag:

```bash
syntagmax analyze .syntagmax/config.toml --no-git
```

## Running Analysis

The `analyze` command is the primary way to process your project. It supports a dynamic execution pipeline where you can request a specific target step.

```bash
syntagmax analyze [CONFIG_FILE] [STEP]
```

### Target Steps

Syntagmax will automatically resolve and execute all dependencies required for the requested step:

| Step | Description |
|------|-------------|
| `extract` | Only extract artifacts from source files. |
| `tree` | Build and validate the artifact tree. |
| `impact` | Perform impact analysis (requires git history). |
| `metrics` | (Default) Calculate project metrics and coverage. |
| `ai` | Perform AI-assisted analysis. |

Example:
```bash
# Run impact analysis only
syntagmax analyze .syntagmax/config.toml impact
```

## Report Output

All analysis outputs (errors, metrics, impact, AI analysis, and optionally the artifact tree) are combined into a single Markdown report file.

- **Default location:** `.syntagmax/reports/report.md`
- **Override with:** `--output <path>` or `--output console` to print to stdout
- **Tree inclusion:** Pass `--render-tree` to include the artifact tree in the report
- **Section order:** Errors → Artifact Tree → Metrics → Impact Analysis → AI Analysis

Example:
```bash
# Generate report with tree to default location
syntagmax --render-tree analyze

# Print report to stdout
syntagmax --output console --render-tree analyze
```

### Task Generation

Syntagmax can automatically generate task files from impact analysis results. Each outdated artifact (suspicious link) produces a dedicated markdown task file tracking the verification work.

Enable in `config.toml`:

```toml
[impact]
enabled = true
tasks_enabled = true
```

Alternatively, use the `--tasks` CLI flag to enable task generation without modifying the config file:

```bash
syntagmax analyze --tasks impact
```

Task files are written to `.syntagmax/tasks/` by default (since `tasks_dir` is resolved relative to the config file directory) and include full references to both parent and child artifacts with their revision information.

For the full configuration reference including custom templates, atype mapping, and de-duplication behavior, see [docs/reference/configuration.md](docs/reference/configuration.md).

## Metamodel DSL

Syntagmax allows defining a custom metamodel for artifacts and their attributes using a simple DSL. This metamodel is used for static validation of requirements and other artifacts.

**Companion VS Code Extension:** [syntagmax-vscode](https://github.com/flyvercity/syntagmax-vscode)

```model
artifact REQ:
    attribute id is mandatory string
    attribute contents is mandatory string
    attribute parent is optional reference to parent
    attribute status is mandatory enum [draft, active, retired]
    attribute verify is optional string
    attribute priority is mandatory integer

trace from REQ to SYS is mandatory via commit
```

For the full syntax reference, types, trace modes, multiple attributes, and impact analysis logic, see [docs/reference/metamodel.md](docs/reference/metamodel.md).

## Editing and Identification

Syntagmax provides a command to assign or update artifact IDs according to a schema. This is useful when you want to ensure a consistent naming convention across your project.

### Quick Editing Demo

```bash
mkdir tmp
cp -rf ./example/renumber-demo ./tmp/
uv run syntagmax --cwd ./tmp/renumber-demo edit identification --all
```

### Identification Command

To assign IDs to artifacts, use the `edit identification` command:

```bash
syntagmax edit identification --all
```

#### Options:
- `--all`: Process all artifacts.
- `--atype <type>`: Process only artifacts of a specific type.
- `--force`: Renumber all artifacts from 1, ignoring existing valid IDs.
- `--dry-run`: Show what changes would be made without actually modifying any files.

### ID Preservation

By default, `edit identification` preserves artifacts that already have valid IDs and only assigns new IDs where needed.

**When IDs are preserved:** Without `--force`, artifacts whose current ID matches the resolved schema (defined in the metamodel via `id is TYPE as SCHEMA`) are never modified. The schema is resolved per artifact type from the metamodel.

**When IDs are renumbered:** Only artifacts with absent, empty, or template IDs (containing literal `{num}` or `{atype}` macros) are renumbered. New IDs start from `max(existing valid numbers) + 1` for each artifact type.

**`--force` mode:** All artifacts are renumbered sequentially from 1, regardless of current ID validity.

**Padding semantics:** `{num:3}` means "at least 3 digits". `REQ-1234` is valid under schema `REQ-{num:3}`. Generated IDs are zero-padded to at least N digits but never truncated.

**Per-type isolation:** Each artifact type (e.g., `REQ`, `SYS`) is numbered independently with its own counter and max tracking.

**Example:**

Before (metamodel schema: `REQ-{num:3}`):
```
file-a.md: REQ-002, <undefined>, REQ-005
file-b.md: REQ-{num:3}, <undefined>
```

After `syntagmax edit identification --all`:
```
file-a.md: REQ-002, REQ-006, REQ-005
file-b.md: REQ-007, REQ-008
```

REQ-002 and REQ-005 are preserved (valid). New IDs start at 006 (max=5, next=6).

After `syntagmax edit identification --all --force`:
```
file-a.md: REQ-001, REQ-002, REQ-003
file-b.md: REQ-004, REQ-005
```

All artifacts renumbered from 1 in sort order.

### Bulk Attribute Manipulation

The `edit attrs` command adds, removes, or replaces attributes across all artifacts in an input section. Only the Obsidian driver is supported.

```bash
syntagmax edit attrs [OPTIONS]
```

#### Options:

| Option | Default | Description |
|--------|---------|-------------|
| `-o, --operation` | `add` | Operation: `add`, `del`, or `replace` |
| `-t, --type` | `attr` | Target: `attr` (YAML) or `field` (inline `[FIELD]`) |
| `-n, --name` | — | Attribute name. Omit for `add` to add all mandatory metamodel attributes. |
| `-l, --value` | `TBD` | Attribute value. Defaults to `TBD` for `add`. |
| `-s, --section` | — | Input record name (required) |
| `--csv` | — | CSV file for per-artifact value lookup |
| `--csv-id-column` | `id` | CSV column for artifact ID matching |
| `--csv-value-column` | `value` | CSV column for attribute value |
| `-d, --csv-delimiter` | `,` | CSV column delimiter |
| `--dry-run` | — | Preview changes without modifying files |

#### Examples (Development Environment):

```bash
# Add all missing mandatory attributes (from metamodel) with TBD
uv run syntagmax --cwd ./example/obsidian-driver edit attrs -s software-requirements --dry-run

# Add 'owner' attribute with TBD to all SYS requirements
uv run syntagmax --cwd ./example/obsidian-driver edit attrs -s system-requirements -n owner
```

#### Examples as a Tool

```bash
# Replace 'status' to 'active' across all REQ artifacts
syntagmax edit attrs -s requirements -o replace -n status -l active

# Remove 'verified' from all artifacts in a section
syntagmax edit attrs -s system-requirements -o del -n verified

# Import values from a CSV file (with --value as fallback for unmatched IDs)
syntagmax edit attrs -s requirements -o replace -n doors_id --csv mapping.csv --csv-id-column ext_id --csv-value-column doors_id -l UNKNOWN
```

#### Behavior Notes:

- **add**: Skips artifacts that already have the attribute. Uses `TBD` if no value given.
- **del**: Removes the attribute wherever it exists; no-op otherwise.
- **replace**: Updates existing values in-place (preserving field position); appends if missing.
- **Metamodel-driven add**: Omit `--name` to add all mandatory attributes defined in the metamodel.
- **CSV mapping**: `--csv` takes precedence; `--value` serves as fallback for unmatched IDs.
- **Atomic writes**: All changes are computed in memory before any file is written.

### Marker Renumbering

The `edit markers renumber` command assigns sequential numeric IDs to non-artifact marked text blocks (e.g., `[COM]`, `[NOTE]`) that don't already have explicit IDs.

```bash
syntagmax edit markers renumber --all
```

#### Options:
- `--all`: Renumber across all input records (required unless `--section` is used).
- `--section <name>`: Restrict to a specific input record.
- `--marker <name>`: Only renumber blocks of a specific marker type.
- `--dry-run`: Show what changes would be made without modifying files.

#### Behaviour:
- Numbering is independent per marker type (COM numbering does not affect NOTE).
- New IDs start from `max_existing + 1` (or 1 if no numeric IDs exist for that type).
- Original marker casing is preserved: `[com]` → `[com 3]`.
- All marker formats are supported: closed (`[COM]...[/COM]`), unclosed, and line-prefix.

#### Examples:

```bash
# Renumber all unmarked blocks
syntagmax edit markers renumber --all

# Preview changes
syntagmax edit markers renumber --all --dry-run

# Only renumber COM markers in system-requirements
syntagmax edit markers renumber --section system-requirements --marker COM
```

## Publishing

Syntagmax can combine project inputs into structured markdown documents, with optional DOCX/PDF export via Pandoc. Rendering is controlled by `publish.yaml` configuration.

```bash
# Publish all records to separate files
syntagmax publish --all

# Single consolidated document with DOCX export
syntagmax publish --all --single --docx --output ./reports/full-document.md
```

For the full command reference, `publish.yaml` schema, rendering configuration, and DOCX template options, see [docs/reference/publishing.md](docs/reference/publishing.md).

### Obsidian Attachment Folder Integration

If your Obsidian vault uses a configured attachment folder (set via Vault Settings → Files & Links → Attachment folder path), Syntagmax can read this setting to resolve image references during publishing.

Enable it in your `config.toml`:

```toml
[drivers.obsidian]
integration = true
```

This reads `.obsidian/app.json` from your project root to find `attachmentFolderPath`, and uses it as the primary lookup location for `![[image.png]]` references. Both vault-relative (e.g. `attachments/pics`) and note-relative (e.g. `./assets`) paths are supported.

For full details, see the [configuration reference](docs/reference/configuration.md#obsidian-driver-driversobsidian).

### Strict Line Breaks

Obsidian treats single newlines as visible line breaks by default, which differs from standard Markdown. The `strict_line_breaks` setting controls whether Syntagmax transforms single newlines into Markdown hard breaks (`  \n`) during extraction.

```toml
[drivers.obsidian]
strict_line_breaks = "off"      # Apply Obsidian-style relaxed line breaks
```

Set to `"auto"` to read the setting from your vault's `.obsidian/app.json` (requires `integration = true`):

```toml
[drivers.obsidian]
integration = true
strict_line_breaks = "auto"
```

For full details, see the [configuration reference](docs/reference/configuration.md#strict-line-breaks).

## Tracing Export

Syntagmax can export artifact traceability relationships as CSV or TSV matrices. The export uses left outer join semantics — every lead artifact appears even if it has no links to the target type.

```bash
syntagmax trace [OPTIONS]
```

### Options

| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `--child <type>` | Yes | — | Artifact type of the child (e.g., `REQ`) |
| `--parent <type>` | Yes | — | Artifact type of the parent (e.g., `SYS`) |
| `--forward` / `--reverse` | No | `--forward` | Direction: forward (child→parent) or reverse (parent→child) |
| `--attribute <name>` | No | — | Additional lead artifact attributes to include (repeatable) |
| `--flat` | No | — | Combine multiple linked IDs into semicolon-separated values |
| `--delimiter <char>` | No | `,` | Column delimiter (auto-detects `\t` for `.tsv` output) |
| `--output <path>` | No | `.syntagmax/reports/trace.csv` | Output path (use `console` for stdout) |
| `-f, --config-file` | No | `.syntagmax/config.toml` | Path to config file |

### Plugin-Based Export

Trace export can be delegated to plugins via the `[trace]` config section:

```toml
[trace]
plugins = ["tsv-export"]
```

When `trace.plugins` is non-empty, all listed plugins run sequentially — each receives the same trace matrix. When the list is empty (or the `[trace]` section is absent), the built-in CSV/TSV writer is used.

Each plugin listed must be declared in a `[[plugin]]` block and implement the `export_trace` hook. See [docs/reference/plugins.md](docs/reference/plugins.md) for the full plugin API.

### Forward vs Reverse

- **Forward** (default): Lead artifacts are children. Each row shows a child ID and its linked parent ID(s).
- **Reverse**: Lead artifacts are parents. Each row shows a parent ID and its linked child ID(s).

### Left Outer Join

All lead artifacts appear in the output even if they have no links to the target type. Unlinked artifacts have an empty linked ID column, making it easy to spot coverage gaps.

### Flat Mode

Without `--flat`, a child with multiple parents produces one row per link. With `--flat`, all linked IDs are combined into a single semicolon-separated cell.

### Examples

```bash
# Forward matrix (REQ → SYS) as CSV
syntagmax trace --child REQ --parent SYS

# Reverse matrix with attributes
syntagmax trace --child REQ --parent SYS --reverse --attribute title

# Flat mode, TSV output
syntagmax trace --child REQ --parent SYS --flat --output .syntagmax/reports/trace.tsv

# Export to stdout
syntagmax trace --child REQ --parent SYS --output console
```

## Plugins

Syntagmax supports a plugin system that allows custom transformations during the publish pipeline. Plugins are distributed separately from the core project — either as local Python files or as installable packages.

Plugins are declared in `config.toml` via `[[plugin]]` blocks and can implement hooks for:

- **`transform_blocks`** — modify the block tree before rendering
- **`transform_markdown`** — transform rendered markdown before writing
- **`filter_block`** — per-block pre-publishing filter (activated via `--pre-filter`)
- **`export_trace`** — custom tracing export format (activated via `[trace] plugins` config)

```toml
[[plugin]]
name = "add-header"
source = "local"
enabled = true

[plugin.params]
title = "My Document"
```

For the full plugin API, configuration options, local/package plugin setup, and working examples, see [docs/reference/plugins.md](docs/reference/plugins.md).

## Change Reports

Syntagmax can generate change reports comparing artifacts between two Git revisions. Reports analyze changes at the artifact level (added, modified, removed requirements) with field-level detail.

### Basic Usage

```bash
# Compare last commit against current HEAD
syntagmax change report --base HEAD~1 --target HEAD

# Compare two tags
syntagmax change report --base v1.2.0 --target v1.3.0

# Compare branches
syntagmax change report --base release --target develop
```

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--base` | (required) | Base Git revision (commit, tag, branch, HEAD, HEAD~N) |
| `--target` | (required) | Target Git revision |
| `--output` | `.syntagmax/reports/change/` | Output directory or `console` for stdout |
| `--include-non-artifact` | off | Include non-artifact text block changes |
| `--single` | off | Generate a single consolidated report |
| `--summary` | off | Generate abbreviated summary report (no content) |
| `-f, --config-file` | `.syntagmax/config.toml` | Path to config file |

### Supported Revisions

- Commit hash (full or short)
- Tag name
- Branch name
- `HEAD`, `HEAD~N`
- `working` — compare against uncommitted changes in the working directory

### Output

Reports are generated per input record with filenames:
```
<section>-<base_rev>-to-<target_rev>-<YYYYMMDD>.md
```

Use `--single` to generate one consolidated report across all records.
Use `--output console` to print to stdout.
Use `--summary` to generate an abbreviated report showing only file paths, changed object IDs, and text fragment locations — no content or attribute diffs are included. Summary reports use the filename suffix `-summary` (e.g. `<section>-...-summary.md`).

```bash
# Quick overview of changes between tags
syntagmax change report --summary --base v1.2.0 --target v1.3.0
```

### Prerequisites

- Git version >= 2.5 (required for worktree support)
- `.syntagmax/worktrees/` must be listed in `.gitignore`

### Example Report Structure

```
# Change Report
## Repository Information
## Summary
## Changed Files (table: Filename | Status | Objects changed)
## Detailed Changes
### Artifacts (grouped by file)
### Text fragments (grouped by file)
### Binary Artifacts (grouped by file)
### Extraction Errors
```

The report includes:
- Summary statistics (files changed, artifacts added/modified/removed)
- Changed files as a table listing affected object IDs and their statuses
- For each modified artifact: text changes rendered as blockquoted markdown and attribute change tables
- For sidecar-managed binary artifacts (images, diagrams): SHA-256 hash comparison, file size, and pixel dimensions (requires optional `Pillow` dependency)
- Fallback plain-text diffs when artifact extraction fails

### Baselining

The `change baseline` command creates a consistent annotated git tag across all repositories that input records point to. This is useful for marking baseline snapshots in multi-repo requirement projects.

```bash
# Create a baseline tag
syntagmax change baseline v1.0.0

# With a custom annotation message
syntagmax change baseline v1.0.0 -m "Release 1.0.0 baseline"

# Preview without creating tags
syntagmax change baseline v1.0.0 --dry-run

# Overwrite existing tags
syntagmax change baseline v1.0.0 --force
```

#### Options

| Option | Default | Description |
|--------|---------|-------------|
| `-m, --message` | `Baseline created by Syntagmax` | Tag annotation message |
| `--force` | off | Overwrite existing tags |
| `--dry-run` | off | Preview actions without creating tags |
| `-f, --config-file` | `.syntagmax/config.toml` | Path to config file |

#### Behaviour

- Discovers all distinct git repositories from input records
- Refuses to proceed if any repo has uncommitted or untracked changes
- Creates annotated tags at HEAD in each repo
- Validates tag name against optional `tag_pattern` regex (see [configuration](docs/reference/configuration.md#baseline-baseline))
- Atomic: if tagging fails in any repo, already-created tags are rolled back
- Prints a push reminder after successful tagging

#### Configuration

Optionally restrict tag names with a regex pattern in `config.toml`:

```toml
[baseline]
tag_pattern = "^v\\d+\\.\\d+\\.\\d+$"
```

## Localization

Syntagmax supports localized report output.

### Configuration

Set the output language in your `config.toml`:

```toml
language = "code"
```

Or use the global CLI flag (overrides the config file):

```bash
syntagmax --lang ru analyze
syntagmax --lang ru change report --base HEAD~1 --target HEAD
```

### Resolution Order

1. CLI `--lang` flag (highest priority)
2. Project `config.toml` `language` field
3. Global `~/.config/syntagmax/config.toml` `language` field
4. Default: `en`

### Scope

Localization applies to:
- Analysis reports (metrics, impact, AI analysis, errors)
- Change reports (full and summary)

It does **not** apply to:
- `publish` command output (renders user content as-is)
- MCP server responses (remain English for LLM compatibility)

## Log Level Control

Syntagmax provides a unified `--log` CLI option to control console log verbosity.

### Available Levels

| Level | Description |
|-------|-------------|
| `debug` | Verbose output including internal diagnostics |
| `info` | Standard operational messages (default) |
| `warning` | Warnings and errors only |
| `error` | Errors only |
| `silent` | Suppress all console output |

### Usage

```bash
# Run with debug logging
syntagmax --log debug analyze

# Suppress warnings
syntagmax --log error analyze

# Treat warnings as fatal errors
syntagmax --warnings-as-errors analyze
```

### Configuration

Log level and warnings behaviour can be set in `config.toml`:

```toml
log_level = "info"
warnings_as_errors = false
```

### Resolution Order

1. CLI `--log` flag (highest priority)
2. Project `config.toml` `log_level` field
3. Global config `log_level` field
4. Default: `info`

### Global Configuration

The global configuration file is located at:
- `$SYNTAGMAX_HOME/config.toml` (if `SYNTAGMAX_HOME` is set)
- `~/.config/syntagmax/config.toml` (default)

Set `SYNTAGMAX_HOME` to override the default global configuration directory.

## Required Improvements

- Implement automatic change propagation
- Enhance AI-based analysis and tracing

## MCP Server

Syntagmax includes a Model Context Protocol (MCP) server that allows LLMs to interact with your requirements directly.

### Tools

- `list_artifacts`: Returns a list of all artifacts in the system.
- `search_artifacts`: Search for requirements by keyword.
- `get_artifact_content`: Fetch full details of a specific requirement (including traceability).

### Running the Server

To start the server using Server-Sent Events (SSE):

```bash
syntagmax mcp run .syntagmax/config.toml --transport sse --port 8000
```

### Sample Configuration

To use Syntagmax with an MCP client that supports SSE, point it to the server's endpoint:

```json
{
  "mcpServers": {
    "syntagmax": {
      "url": "http://127.0.0.1:8000/sse"
    }
  }
}
```

Note: When running via SSE, the server must be started manually or managed by a process manager before the client connects.
