Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ jobs:
marker: legis_e2e
- name: Filigree
marker: filigree_e2e
- name: Warpline
marker: warpline_e2e
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -176,6 +178,7 @@ jobs:
WARDLINE_LOOMWEAVE_BIN: ${{ secrets.WARDLINE_LOOMWEAVE_BIN }}
WARDLINE_LEGIS_URL: ${{ secrets.WARDLINE_LEGIS_URL }}
WARDLINE_FILIGREE_URL: ${{ secrets.WARDLINE_FILIGREE_URL }}
WARDLINE_WARPLINE_BIN: ${{ secrets.WARDLINE_WARPLINE_BIN }}
- name: Summarize live oracle
if: always()
run: |
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- **Warpline delta scan (`wardline scan --affected`).** A new `--affected
<file|->` option scopes analysis to the entities named in a `warpline.
reverify_worklist.v1` worklist (or a bare entity list, file or stdin), so an
agent's inner loop can re-verify only what changed. The affected set is
caller-closure expanded so cross-file taint into a changed callee is still
computed; the displayed findings are filtered to the requested entities while
the severity gate evaluates the full unsuppressed population **of the analyzed
files**, so an attacker-influenceable scope cannot hide an in-analyzed-file
finding from the gate (INV-4). Advisory, not a gate: delta analyzes only the
scoped (caller-closure-expanded) files, so it cannot certify files it never
analyzed — `--affected` is therefore **rejected together with `--fail-on`**
(and over MCP, `affected` with `fail_on`); use `--new-since` for an
authoritative change-scoped gate (full analysis, gates the changed subset) or
a full scan for the gate of record. An empty or all-unresolvable scope falls
back to a full scan. A `scope` block (mode,
gate authority, file counts, unresolved/fell-back/stale-SEI accounting, and a
boundary caveat) is attached to every output format (agent-summary JSON,
SARIF `run.properties`, MCP structured content). Delta emits on both the CLI
and MCP surfaces force `mark_unseen=False` so a scoped run never poisons
Filigree reconciliation.
- **MCP `scan` gains an `affected` parameter.** The same delta scope (inline
object/array worklist or a path under root) is available over MCP, with the
`scope` block surfaced in structured content.
- **`warpline_e2e` live oracle.** A scheduled/manual CI oracle runs the real
`warpline reverify` → `wardline scan --affected -` round-trip; the marker is
fail-closed under `WARDLINE_LIVE_ORACLE_REQUIRED`.

## [1.0.3] - 2026-06-18

### Fixed
Expand Down
158 changes: 79 additions & 79 deletions docs/audits/2026-06-08-comprehensive-audit.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ The fields:
| `location` | The source `path` plus `line_start`/`line_end` and `col_start`/`col_end`. |
| `message` | A human-readable description of the violation. |
| `properties` | Rule-specific detail. Here, the declared vs. actually-returned trust tier. |
| `suppressed` | `active` means the finding is live (not suppressed). |
| `suppression_state` | `active` means the finding is live (not suppressed); other states are `baselined`, `waived`, `judged`. |
| `suppression_reason` | Why it was suppressed, if it was; `null` for a live finding. |
| `confidence`, `suggestion` | Optional extras, `null` when the rule does not supply them. |
| `related_entities` | Other entities involved in the finding, if any. |
Expand Down
74 changes: 66 additions & 8 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,67 @@ Usage: wardline scan [OPTIONS] [PATH]

Scan PATH for findings.

PATH is the scan root and GOVERNS finding identity: qualnames and
fingerprints are minted relative to it, and baseline/waiver/judged
suppression state is read from PATH's .weft/wardline/. Scan the project root.

Options:
--config FILE Path to a weft.toml whose [wardline] table
supplies configuration overrides (weft.toml).
--config FILE
--format [jsonl|sarif|agent-summary|legis]
--lang [python|rust] Language frontend. 'rust' (PREVIEW) scans
.rs files for command-injection findings.
--lang [python|rust] Language frontend. 'rust' scans .rs files
for RS-WL-* command-injection findings
(frozen identity, baseline-eligible; config
severity overrides not yet applied).
--output PATH
--fail-on [CRITICAL|ERROR|WARN|INFO]
--cache-dir PATH Store authenticated L3 summary-cache entries
here for faster incremental scans when
WARDLINE_SUMMARY_CACHE_KEY is set.
--fail-on [critical|error|warn|info]
--fail-on-unanalyzed / --no-fail-on-unanalyzed
Exit 1 if any file was discovered but could
not be analyzed.
--cache-dir PATH Persist L3 summary cache here for faster
incremental scans.
--filigree-url TEXT POST findings to this Filigree Weft scan-
results URL (opt-in).
--local-only, --no-emit Disable sibling emission even when Filigree
or Loomweave URLs resolve from flags, env,
or local install state.
--filigree-max-findings-per-request INTEGER RANGE
Maximum Wardline findings per Filigree scan-
results POST (default 1000). [x>=1]
--loomweave-url TEXT Persist per-entity taint facts to this
Loomweave taint-store URL (opt-in, fail-
soft).
--new-since TEXT PR-scoped 'new findings only' gate: only
gate on findings in files/entities changed
since this git ref.
--affected FILENAME Scan only entities in this warpline
reverify-worklist / entity-list (file path,
or '-' for stdin). Advisory delta, not a gate:
out-of-scope cross-file flows are not analyzed
(see the scope block), so it cannot drive
--fail-on (use --new-since to gate changed
code, or a full scan for the gate of record).
Empty/unresolvable -> full scan. Mutually
exclusive with --new-since and --fail-on.
--trust-pack TEXT Allow importing this trust-grammar pack from
weft.toml [wardline]. May be repeated.
--allow-custom-packs Allow loading custom trust-grammar packs
from the local project directory.
--fix Apply mechanical autofixes during the scan.
-y, --yes Automatically confirm all fixes when --fix
is specified.
--strict-defaults Ignore repository-supplied custom
configuration overrides (weft.toml).
--allow-source-root-escape Allow weft.toml [wardline] source_roots to
resolve outside PATH.
--trust-suppressions Let repository-controlled
baseline/waiver/judged files clear the
--fail-on gate (always annotate findings
regardless). Default off: the gate evaluates
the unsuppressed population so a PR cannot
self-suppress.
--allow-dirty For --format legis only: on a dirty working
tree, emit an UNSIGNED, clearly-marked dev
artifact instead of refusing.
--help Show this message and exit.
```

Expand All @@ -112,6 +160,16 @@ it at a package root, not a single file.
| `--filigree-url TEXT` | Opt-in: POST findings to a Filigree Weft scan-results endpoint as well as emitting them locally. Prefer this native path when agents need Filigree promotion, deduplication, or close/reopen lifecycle state. |
| `--local-only`, `--no-emit` | Disable sibling emission for this scan, even if Filigree or Loomweave URLs resolve from flags, environment, MCP install state, or local published ports. The scan still writes local output and evaluates the gate. |
| `--filigree-max-findings-per-request INTEGER` | Cap findings per Filigree scan-results POST. Precedence is explicit CLI value, then `WARDLINE_FILIGREE_MAX_FINDINGS_PER_REQUEST`, then Filigree's advertised scan-results limit from `/api/files/_schema` when reachable, then Wardline's safe default (`1000`). Wardline chunks by complete file groups when possible so Filigree reconciliation does not mark later chunks as fixed. |
| `--loomweave-url TEXT` | Opt-in, fail-soft: persist per-entity taint facts to a Loomweave taint-store endpoint alongside local output. |
| `--fail-on-unanalyzed` / `--no-fail-on-unanalyzed` | Exit `1` if any file was discovered but could not be analyzed (e.g. a parse failure), even when no finding trips `--fail-on`. |
| `--new-since TEXT` | PR-scoped "new findings only" gate: gate only on findings in files/entities changed since this git ref. Mutually exclusive with `--affected`. |
| `--affected FILENAME` | Scope analysis to the entities named in a `warpline.reverify_worklist.v1` worklist (or a bare entity list; file path, or `-` for stdin) — the inner-loop fast path. The affected set is caller-closure expanded so cross-file taint into a changed callee is still computed. **Advisory, not a gate:** only the scoped files are analyzed, so it cannot certify out-of-scope files and is **rejected together with `--fail-on`** — use `--new-since` for an authoritative change-scoped gate (full analysis, gates the changed subset) or a full scan for the gate of record (a `scope` block records the mode, gate authority, and `analyzed N of M` accounting). An empty or all-unresolvable scope falls back to a full scan. Mutually exclusive with `--new-since` and `--fail-on`. |
| `--trust-pack TEXT` (repeatable), `--allow-custom-packs` | Allow loading trust-grammar packs declared in `weft.toml [wardline]` (`--trust-pack`) or from the local project directory (`--allow-custom-packs`). |
| `--fix`, `-y`/`--yes` | Apply mechanical autofixes during the scan; `-y` auto-confirms every fix. |
| `--strict-defaults` | Ignore repository-supplied custom configuration overrides in `weft.toml`. |
| `--allow-source-root-escape` | Allow `weft.toml [wardline] source_roots` to resolve outside `PATH`. |
| `--trust-suppressions` | Let repository-controlled baseline/waiver/judged files clear the `--fail-on` gate (they always annotate findings regardless). Use only for trusted local checkouts; in CI prefer the unforgeable `--new-since <merge-base>` ratchet. Default off, so the gate evaluates the unsuppressed population and a PR cannot self-suppress. |
| `--allow-dirty` | `--format legis` only: on a dirty working tree, emit an UNSIGNED, clearly-marked (`dirty: true`) dev artifact instead of refusing. Signing stays clean-tree-only. |

Realistic invocation — scan the source tree, emit SARIF to a file, and fail the
build on any `ERROR`-or-worse finding:
Expand Down
Loading
Loading