# Agents

Orientation for coding agents working on this repository.

---

## What this repo is

An NLSpec for `traceable-reqs`, a Rust CLI for requirements tracing, plus the reference implementation under `rust/`. The expected agent tasks are:

1. Implement the CLI against `SPEC.md`.
2. Verify an implementation against `SPEC.md` and the `example/` fixture.
3. Refine the spec without scope creep.

---

## Sources of truth

- `SPEC.md` — authoritative behavior.
- `example/expected.json` — golden output for the bundled fixture.
- `SPEC-CHANGE.md` — draft spec for the `change` subsystem;
  `example/expected-change-compile.json` is its golden output. SPEC.md
  wins on any kernel behavior it touches.
- `WORKFLOW.md` — non-normative: how callers drive the change loop and
  where each non-deterministic step lives. The specs win on behavior.

If `SPEC.md` and `README.md` disagree, `SPEC.md` wins.

---

## Implementation language

Rust. Do not propose another language without explicit user direction.

---

## Common pitfalls

- The manifest is **required**. Tags never create requirement IDs.
- Scan candidates come from **git** inside a work tree (tracked plus untracked-not-ignored), not from a filesystem walk. `scan.roots` filters that set; it never widens it. `[scan].git = "off"` forces the walk. Outside a work tree the walk is the fallback and is not an error.
- Tag grammar is strict: `[stage->REQ-ID]`, no internal spaces. Bracketed text is tag-shaped when its text before `->`, after trimming, has stage-name shape `[a-z][a-z0-9_-]*`; a tag-shaped token that does not match exactly is a `parse_error`. Other bracketed arrow text is ignored.
- Tags count only **inside comments** for Rust, C, C++, and Python. Markdown scans every physical line, including HTML comments.
- Rust/C/C++ block comments are scanned by physical line, with the `/* ... */` range inclusive of both ends.
- Built-in stage vocabulary (`doc`, `impl`, `unit`, `int`) is fixed. Core also accepts manifest-declared custom stages and external signoff evidence.
- Finding codes (`missing_stage`, `undeclared_id`, `parse_error`, `manifest_error`, `scan_error`, `misplaced_tag`) are stable. Do not invent new codes.
- `check` enforces tag placement by default, so a tag must be attached to an item that can carry its stage (SPEC.md §Tag placement enforcement). Test fixtures that write a bare tag into an otherwise empty file, or a banner above a file's imports, now produce `misplaced_tag`; give the fixture a real item or set `[placement].enforce = "off"` in that fixture's manifest.
- `requirements[].stages` in JSON output always contains all four stage keys, regardless of which are required.
- Evidence paths in JSON are repository-relative with `/` separators. Line numbers are 1-based.

---

## Validating against the fixture

From the repo root:

```text
cd example
traceable-reqs check --json > actual.json
```

Compare against `example/expected.json` per the rules in `example/README.md`:

- `requirements[]` and `findings[]` are sets — sort before diffing (e.g. `jq -S` plus `sort_by`).
- Only `code`, `requirementId`, `stage`, `path`, and `line` are stable. `message` text is illustrative.

The fixture exercises acceptance examples 1–5, 7, and 8. `manifest_error` and `scan_error` are operational; cover them in the implementation's own test harness.

---

## Out of scope

The README's non-goals are binding. In particular, do not add:

- IDE plugins or language servers.
- ReqIF or full OpenFastTrace interchange.
- Anything that replaces GitHub Issues or another planner.

The optional capabilities listed in `SPEC.md` (priority gates, scan extension/exclusion configuration, requirement groups, and manifest `version`) are not part of core. Leave them out unless the task asks for them. Custom stages and external signoff evidence are core capabilities.

---

## Pull requests

- Cite the `SPEC.md` section your change targets.
- Behavior changes should add or update a fixture case under `example/`.
- Behavior changes must add an entry under `[Unreleased]` in `CHANGELOG.md`
  ([Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format). Cutting a
  release promotes that section to the new version; the GitHub release notes
  are taken from it.
- Changes to finding codes, tag grammar, or JSON schema require a `schemaVersion` discussion in the PR.
