Skip to content

Releases: AstralXVoid/NoWreck

NoWreck v0.9.0 — Rust + Go Language Support

Choose a tag to compare

@AstralXVoid AstralXVoid released this 19 Aug 11:03

NoWreck v0.9.0 — Rust + Go Language Support

Release date: August 2026
Previous release: v0.8.0 (Type-Level Claim Types)
Focus: Rust and Go language support via tree-sitter grammars. Two new scanner modules, extended repository scanner, change detector, and symbol index — all following the existing architecture pattern exactly. Zero new claim types, zero changes to the verification engine, reporter, or JSON schema.


What's new in v0.9.0

Rust scanning ✅

Rust source files (.rs) are now parsed with the tree-sitter-rust grammar. The scanner extracts:

fn add(a: i32, b: i32) -> i32 { a + b }FUNCTION "add"
pub fn connect(addr: &str) -> Result<()> { ... }FUNCTION "connect"
struct User { name: String, age: u32 }CLASS "User"
impl User { fn display(&self) { ... } }METHOD "display" (parent_class: "User")
trait Display { fn fmt(&self); }INTERFACE "Display"
impl Display for User { fn fmt(&self) { ... } }METHOD "fmt" (parent_class: "User")
enum Role { Admin, Member, Guest }ENUM "Role"
type Result<T> = std::result::Result<T, Error>TYPE_ALIAS "Result"
  • pub/pub(crate) visibility modifiers are unwrapped (like export in TS)
  • mod declarations are skipped (structural namespaces, not symbols)
  • impl block methods are extracted with parent_class set to the impl target
  • trait methods are NOT extracted as METHOD symbols (same one-level-deep philosophy)
  • Macro invocations (println!, format!) are NOT treated as function calls

Go scanning ✅

Go source files (.go) are parsed with the tree-sitter-go grammar:

func Add(a, b int) int { return a + b }            → FUNCTION "Add"
func (u *User) Display() { fmt.Println(u.Name) }   → METHOD "Display" (parent_class: "User")
type User struct { Name string; Age int }           → CLASS "User"
type Reader interface { Read(p []byte) (n int, err error) }  → INTERFACE "Reader"
type Status stringTYPE_ALIAS "Status"
  • type X struct → CLASS (structs are Go's primary data-carrying type)
  • type X interface → INTERFACE (method sets)
  • type X string → TYPE_ALIAS (type renames)
  • Receiver types extracted from method declarations for parent_class
  • const and var declarations are skipped (value bindings, not symbols)
  • Selector expressions (fmt.Println()) are NOT treated as simple function calls

Architecture

Both scanners follow the exact same pattern as the TypeScript scanner:

  1. Lazy-load grammar on first call (per-process singleton)
  2. Parse file with tree-sitter
  3. Walk CST, collect top-level declarations
  4. Return Symbol objects compatible with the shared pipeline
  5. Call detection via call_expression with simple identifier targets

The repository scanner discovers .rs and .go files alongside .py, .js, .ts, and .tsx. The symbol index, change detector, and verification engine all work unchanged — they see Symbol objects and DetectedChange objects, never knowing which language produced them.


Scope boundary

  • .py/.js/.ts/.tsx existing behaviour — byte-identical to v0.8.0 (hard gate)
  • Same 13 claim types — Rust/Go use the existing types
  • No new SymbolType, ChangeType, or ClaimType members
  • Verifier, reporter, prompts — zero changes
  • JSON schema — zero changes (additive language support)
  • 2 new dependencies: tree-sitter-rust, tree-sitter-go

Test suite

Suite v0.8.0 v0.9.0 Growth
pytest (project unit tests) 453 453
Milestone 1 checkpoint 60 tests 80 tests +20
Change detector 57 tests 57 tests
Verifier 55 tests 55 tests
Terminal reporter 45 tests 45 tests
ruff 0 issues 0 issues
basedpyright 0 errors 0 errors

+20 new milestone tests:

  • TestPureRustRepo (9 tests): file discovery, greeter symbols, calculator class+methods, models types (struct, trait, enum, type alias), symbol index counts, call detection, file changes, no-change determinism, cross-run determinism
  • TestPureGoRepo (9 tests): file discovery, greeter symbols, calculator class+methods, models types (struct, interface, type alias), symbol index counts, call detection, file changes, no-change determinism, cross-run determinism
  • TestAllReposDeterministic extended: Rust and Go repos added to cross-repo determinism parametrize (7 repos total)

File changes

New files

File What it covers
nowreck/scanner/rust_scanner.py Rust scanner (lazy grammar, scan_rust_file, scan_rust_calls)
nowreck/scanner/go_scanner.py Go scanner (lazy grammar, scan_go_file, scan_go_calls)
test_milestone1/repos/pure-rust/src/ Milestone repo: greeter.rs, calculator.rs, models.rs
test_milestone1/repos/pure-go/src/ Milestone repo: greeter.go, calculator.go, models.go
docs/nowreck-v9-scope.md Full scope document
docs/release9.md This release notes file

Modified files

File What changed
nowreck/scanner/repository_scanner.py Added rust_files/go_files to ScanResult; added _discover_rust_files, _discover_go_files, _parse_rust_file, _parse_go_file
nowreck/scanner/symbol_index.py build_symbol_index now processes rust_files and go_files
nowreck/detector/change_detector.py _detect_file_changes includes Rust/Go files; _extract_calls includes Rust/Go call detection
test_milestone1/test_milestone1_checkpoint.py TestPureRustRepo, TestPureGoRepo classes; extended TestAllReposDeterministic
pyproject.toml Dependencies: +tree-sitter-rust>=0.23, +tree-sitter-go>=0.25

Unchanged

  • nowreck/scanner/javascript_scanner.py0 changes
  • nowreck/scanner/typescript_scanner.py0 changes
  • nowreck/scanner/_tree_sitter_helpers.py0 changes
  • nowreck/claims/0 changes
  • nowreck/verifier/verifier.py0 changes
  • nowreck/model/prompts.py0 changes
  • nowreck/reporter/terminal_reporter.py0 changes (version bump only)
  • nowreck/picker.py, CLI — 0 changes
  • JSON output schema — 0 changes
  • .py/.js/.ts/.tsx existing scanning behaviour — byte-identical (hard gate)

Installing / upgrading

pipx install .    # fresh install from repo
pip install -e .  # or editable install

Requires Python 3.10+. No new system dependencies (tree-sitter grammars ship as Python wheels).

nowreck --version
# → nowreck 0.9.0

Definition of Done ✅

  1. A .rs file with functions, structs, impl methods, traits, enums, and type aliases scans to the correct SymbolTypes and line numbers — verified by hand — and nowreck fix --pre <empty> --post <pure-rust> detects expected changes matching reality.
  2. A .go file with functions, methods, structs, interfaces, and type aliases scans to the correct SymbolTypes and line numbers — verified by hand — and nowreck fix --pre <empty> --post <pure-go> detects expected changes matching reality.
  3. .py/.js/.ts/.tsx repos produce output byte-identical to v0.8.0 for all previously-supported symbols.
  4. The full existing test battery passes, plus the new Rust/Go milestone tests.
  5. ruff: 0 issues, basedpyright: 0 errors.

Result (verified):

  • Pure-Rust milestone repo: 3 files, 19 symbols detected (functions, structs, methods, trait, enum, type alias). CLI detects all 19 as ADD_FUNCTION/ADD_CLASS/ADD_INTERFACE/ADD_ENUM/ADD_TYPE_ALIAS changes.
  • Pure-Go milestone repo: 3 files, 18 symbols detected (functions, methods, structs, interface, type alias). CLI detects all 18 as ADD_FUNCTION/ADD_CLASS/ADD_INTERFACE/ADD_TYPE_ALIAS changes.
  • All existing repos (pure-python, pure-js, pure-ts, pure-tsx, mixed) produce identical output to v0.8.0.
  • 453 pytest tests pass, 80 milestone tests pass, ruff clean, basedpyright clean.

What's next

The roadmap remains focused on narrow, testable increments, each with its own scope document and phase-by-phase build discipline.

  • explanation field on claims — model + prompt change (README documents it, the Claim model doesn't have it yet) — deferred from v6
  • Scan-summary expansion in verbose mode (per-language file counts) — deferred from v6
  • TS polish (from v5): abstract methods, constructor parameter properties, decorators — separate polish increment
  • Interface method signatures / enum members as symbols — polish increment, not done yet
  • Python type-level capture — Python's Enum/TypeAlias/TypedDict mapping needs its own design conversation
  • Independent verification architecture (fix Prompt Mode circularity) 🗓 (planned for v0.10.0 — see docs/nowreck-v10-scope.md)
  • Additional model providers (Anthropic, Gemini)
  • Caching for large repositories
  • CI/CD integration

NoWreck v0.8.0 — Type-Level Claim Types (Interfaces, Enums, Type Aliases)

Choose a tag to compare

@AstralXVoid AstralXVoid released this 18 Aug 18:51

NoWreck v0.8.0 — Type-Level Claim Types (Interfaces, Enums, Type Aliases)

Release date: August 2026
Previous release: v0.7.0 (TSX Support)
Focus: interface, enum, and type alias declarations as first-class claim types for the TS/TSX family. Six new claim types (ADD/REMOVE × INTERFACE/ENUM/TYPE_ALIAS), wired through scanner, change detector, claim parser, verifier, prompts, and reporter. Zero new dependencies. Zero changes to JS/Python behaviour.


What's new in v0.8.0

Type-level claim types ✅

TypeScript codebases define contracts at the type level (interface, enum, type aliases) that were invisible to Nowreck until now. The scanner ignored them, so they never appeared as symbols, changes, or claims. v0.8.0 makes them first-class — captured, detected, claimable, and verifiable — for the TS/TSX family.

What gets captured (TS/TSX only):

interface User { id: number; name: string }         INTERFACE "User"
enum Color { Red, Green, Blue }                      ENUM "Color"
type Status = "active" | "inactive"                  TYPE_ALIAS "Status"
export interface Props { ... }                       (unwrapped, same as above)
export default interface Thing { ... }               (named, collected)

What stays unchanged:

  • Members are NOT captured — interface method signatures, enum members, and generic parameters remain structural detail, not symbols (same one-level-deep philosophy as class methods)
  • Python's class Color(Enum) stays ADD_CLASS (byte-identity gate)
  • .ts/.js/.py existing behaviour — byte-identical to v0.7.0 (hard gate)
  • No new dependencies, no JSON schema break (additive only)

The design decision: per-kind claim types

Three distinct pairs — ADD_INTERFACE/REMOVE_INTERFACE, ADD_ENUM/REMOVE_ENUM, ADD_TYPE_ALIAS/REMOVE_TYPE_ALIAS — rather than one folded ADD_TYPE/REMOVE_TYPE pair. The existing taxonomy is per-kind (FUNCTION ≠ CLASS), and the scanner knows the exact declaration kind from the CST node type. Folding into a single TYPE pair would blur interface-vs-alias in reports and make model mislabelling less detectable.

Pipeline wiring (8 touch points, mechanical additive changes)

# Location Change
1 nowreck/scanner/symbol_index.py SymbolType: +INTERFACE, +ENUM, +TYPE_ALIAS; interfaces/enums/type_aliases properties
2 nowreck/scanner/_tree_sitter_helpers.py collect_top_level_symbols: collect interface_declaration, enum_declaration, type_alias_declaration
3 nowreck/detector/change_detector.py ChangeType: +6; _symbol_to_change mapping
4 nowreck/claims/models.py ClaimType: +6; CLAIM_TYPE_NAMES: +6 entries
5 nowreck/verifier/verifier.py _SAME_CHANGE: +6; _OPPOSITE_CHANGE: +6
6 nowreck/model/prompts.py _CLAIM_TO_CHANGE_TYPE: +6; schema example + field notes
7 nowreck/reporter/terminal_reporter.py Labels + evidence lines for new kinds
8 nowreck/claims/parser.py Inherits CLAIM_TYPE_NAMES from models (no local copy)

Scope boundary

  • TS/TSX type-level scanning, symbol extraction, change detection, claims, and verification — in
  • .ts/.tsx/.js/.py existing behaviour — byte-identical to v0.7.0 (hard gate)
  • Python enums/typed-anything — out (stays ADD_CLASS/uncaptured)
  • Interface members, enum members, generic parameters — out (polish increment later)
  • No new dependencies, no caching, no new model providers, no reporter/CLI/picker feature changes beyond additive labels

Test suite growth

Suite v0.7.0 v0.8.0 Growth
pytest (project unit tests) 469 453 −16 (test__no_type_level tests removed as behaviour changed)*
Milestone 1 checkpoint (4 repos) 57 tests 60 tests +3
Change detector (incl. TSX + type-level) 47 tests 57 tests +10
Verifier (incl. type-level) 39 tests 55 tests +16
Terminal reporter (incl. type-level labels) 34 tests 45 tests +11
Model/prompt builder (incl. type-level) 37 tests 45 tests +8
Claims parser 21 tests 21 tests
ruff 0 issues 0 issues
basedpyright 0 errors 0 errors

New test coverage added across:

  • tests/test_change_detector.pyTestDetectTypeLevelChanges (9 tests): interface add/remove, enum add/remove, type alias add/remove, type replaced in single file, multiple type-level changes, no changes when identical
  • tests/test_verifier.pyTestClaimVerifierTypeLevel* (15 tests): add/remove confirmed, add/remove contradicted, no changes / wrong name / wrong file unverifiable — for all three type-level kinds
  • tests/test_terminal_reporter.py — type-level labels and evidence (6 tests): add interface/enum/type alias evidence lines, remove interface/enum/type alias evidence lines, claim descriptions
  • tests/test_model.pyclaims_to_changes for new types (6 tests): add/remove interface, enum, type alias mapping
  • test_milestone1/test_milestone1_checkpoint.py — type-level assertions (3 tests): test_type_level_symbols_captured (pure-ts + pure-tsx), test_type_level_change_detection (pure-ts)
  • test_ts_samples/test_phase1_comprehensive.py — type-level positive tests: interface, type alias, enum captured with correct SymbolType and line numbers (previously negative tests asserting NOT captured)
  • test_ts_samples/test_phase1_comprehensive_tsx.py — type-level positive tests: same for TSX samples (previously negative tests)
  • test_ts_samples/test_phase1_multiround_tsx.py — type-level round check: ButtonProps interface now captured

File changes

Modified files

File What changed
nowreck/scanner/symbol_index.py SymbolType: +INTERFACE, +ENUM, +TYPE_ALIAS; interfaces/enums/type_aliases properties
nowreck/scanner/_tree_sitter_helpers.py collect_top_level_symbols: collect interface_declaration, enum_declaration, type_alias_declaration
nowreck/detector/change_detector.py ChangeType: +6; _symbol_to_change mapping for INTERFACE/ENUM/TYPE_ALIAS
nowreck/claims/models.py ClaimType: +6; CLAIM_TYPE_NAMES: +6 entries
nowreck/claims/parser.py CLAIM_TYPE_NAMES now imported from models (no local copy)
nowreck/verifier/verifier.py _SAME_CHANGE: +6; _OPPOSITE_CHANGE: +6
nowreck/model/prompts.py _CLAIM_TO_CHANGE_TYPE: +6; _CHANGE_LABELS: +6; JSON schema updated to 13 claim types
nowreck/reporter/terminal_reporter.py _CLAIM_TYPE_LABELS: +6; _CHANGE_TYPE_LABELS: +6; evidence-line builders for new kinds
test_milestone1/repos/pure-ts/src/models.ts Added interface (UserProfile), enum (Role), type alias (UserStatus)
test_milestone1/repos/pure-tsx/src/models.tsx Added enum (ViewMode), type alias (SortOrder); UserProps interface already present
test_milestone1/test_milestone1_checkpoint.py New test_type_level_symbols_captured, test_type_level_change_detection; pure-tsx test_type_level_symbols_captured
tests/test_change_detector.py TestDetectTypeLevelChanges class (9 tests); test_values_are_distinct updated to len(ChangeType)
tests/test_verifier.py TestClaimVerifierTypeLevelConfirmed (6), TestClaimVerifierTypeLevelContradicted (6), TestClaimVerifierTypeLevelUnverifiable (3)
tests/test_terminal_reporter.py Type-level evidence line tests, claim description tests
tests/test_model.py test_claims_to_changes_add_interface, remove_interface, add_enum, remove_enum, add_type_alias, remove_type_alias, test_prompt_renders_interface_change
test_ts_samples/test_phase1_comprehensive.py Negative interface/type/enum tests → positive (now captured); added SymbolType + line number assertions
test_ts_samples/test_phase1_comprehensive_tsx.py Negative interface/type/enum tests → positive (now captured); added SymbolType assertions
test_ts_samples/test_phase1_multiround_tsx.py ButtonProps interface now captured
test_ts_samples/edge_types_only.ts Comment updated: negative test → positive test since v0.8.0

Unchanged

  • nowreck/scanner/typescript_scanner.py0 changes (helpers are grammar-agnostic)
  • nowreck/scanner/repository_scanner.py0 changes
  • nowreck/scanner/javascript_scanner.py0 changes
  • nowreck/picker.py, CLI, JSON schema structure — 0 changes
  • .ts/.tsx/.js/.py existing scanning behaviour — byte-identical (hard gate)
  • Dependencies — 0 new packages

Installing / upgrading

pipx install .    # fresh install from repo
pip install -e .  # or editable install

Requires Python 3.10+. No new dependencies.

nowreck --version
# → nowreck 0.8.0

Claim types: 7 → 13

Previous (7) v0.8.0 adds (6)
ADD_FUNCTION ADD_INTERFACE
REMOVE_FUNCTION REMOVE_INTERFACE
ADD_CLASS ADD_ENUM
REMOVE_CLASS REMOVE_ENUM
FILE_CREATED ADD_TYPE_ALIAS
FILE_DELETED REMOVE_TYPE_ALIAS
CALLS_FUNCTION

The type field in the JSON output gains six new allowed string values. Every existing value and field is unchanged. Additive, not breaking — old consumers keep working.


Definition of Done ✅

  1. A .ts/.tsx file with interfaces, enums, and type aliases scans to the correct SymbolTypes and line numbers — verified by hand against the source — and nowreck fix --pre <empty> --post <repo> detects the expected ADD_INTERFACE / ADD_ENUM / ADD_TYPE_ALIAS changes matching reality.
  2. .ts/.tsx/.js/.py repos produce output **byte-iden...
Read more

NoWreck v0.7.0 — TSX (`.tsx`) Support Release

Choose a tag to compare

@AstralXVoid AstralXVoid released this 16 Aug 17:53
9019ab0

NoWreck v0.7.0 — TSX (.tsx) Support Release

Release date: August 2026
Previous release: v0.6.0 (Verbose Mode)
Focus: .tsx files (TypeScript + JSX) scan, symbol-extract, call-extract, change-detect, and verify — folded into the existing TypeScript family. Zero new dependencies (the TSX grammar ships with the already-used tree-sitter-typescript package), zero changes to the verifier, reporter, claim types, or JSON schema.


What's new in v0.7.0

.tsx file support ✅

React components are ordinary functions, arrow-function consts, and classes — all already covered by the existing SymbolType set. The scanner now parses .tsx files with the TSX grammar (language_tsx(), from the same package v5 already depends on) and feeds the exact same symbols and calls through the existing pipeline:

  • function App() { return <div/> } → FUNCTION
  • const App = () => <div/> → FUNCTION (arrow assignee)
  • class App extends React.Component { render() { return <div/> } } → CLASS + METHOD (render)
  • onClick={() => doThing()} → nested named arrows are collected as callers; identifier handlers (onClick={handleClick}) and member calls (this.toggle()) are ignored — same rules as .ts/.js
  • export default function App() {...} → collected; anonymous export default () => <div/> → ignored (no name)
  • Fragments, generics, interfaces, nested components — parsed, no crashes

JSX elements are expressions, not symbols or calls. <div>, <Component/>, and JSX attributes never become symbols or calls — verified by hand and by test.

The design decision: fold into the TS family

.tsx is the same language as .ts — same grammar package, same symbol shapes, same 7 claim types. So .tsx files fold into the existing ScanResult.ts_files field rather than getting a parallel tsx_files field. scan_ts_file() / scan_ts_calls() dispatch on file extension; _discover_ts_files() matches both *.ts and *.tsx; symbol_index, change_detector, picker, and the JSON schema needed zero changes.

Scope boundary

  • .ts / .js / .py behaviour — byte-identical to v0.6.0 (hard gate)
  • Same 7 claim types — interfaces, enums, and type aliases in .tsx/.ts remain uncaptured (they need new claim types first; still deferred)
  • No JSX-element symbols — markup is not a symbol
  • No new dependencies, no verifier/reporter changes, no JSON schema changes

Test suite growth

Suite v0.6.0 v0.7.0 Growth
pytest (project unit tests) 449 469 +20
TS comprehensive 42 tests 42 tests
TS multi-round 29 tests 29 tests
TSX comprehensive (new) 54 tests +54
TSX multi-round (new, 7 rounds) 36 tests +36
JS comprehensive 101 tests 101 tests
JS multi-round 80 tests 80 tests
Milestone 1 checkpoint (4 repos) 45 tests 57 tests +12
Milestone 1 demo (5 repos incl. pure-tsx) Clean Clean
Change detector (incl. new TSX class) 39 tests 47 tests +8
Live hallucination-catch tests (JS + TS + TSX) PASS PASS
ruff 0 issues 0 issues
basedpyright 0 errors 0 errors

+20 new pytest tests, broken down as:

  • tests/test_change_detector.pyTestDetectTsxChanges (8 tests): component add → ADD_FUNCTION, component remove → REMOVE_FUNCTION, replace in single file → add + remove, class component → ADD_CLASS + method (folds to ADD_FUNCTION with parent_class, same as .ts/.js), TSX call detected, <Child/> usage NOT a call, identical pre/post → no changes, file create/delete
  • test_milestone1/test_milestone1_checkpoint.pyTestPureTsxRepo (12 tests): discovery (3 files), greeter components, calculator class + methods, models components, symbol counts, call detection, console.log excluded, JSX-element-usage-not-a-call, file changes, no-change, determinism; pure-tsx added to cross-repo determinism and pre/post no-change loops

New sample suites (test_ts_samples/):

  • test_phase1_comprehensive_tsx.py — 54 tests: component shapes, handlers and nested arrows, exports/generics/interfaces, anonymous default exports, mixed edge cases (IIFE skip, interface/type/enum negatives, calls in JSX-in-body), error handling, repo_root relativisation, determinism
  • test_phase1_multiround_tsx.py — 36 tests across 7 rounds: symbol repeatability ×3, call repeatability ×3 + known-call set, 660-symbol stress file, path variants, real-world React patterns, line-number accuracy, chaos test

New sample files: edge_tsx_components.tsx, edge_tsx_handlers.tsx, edge_tsx_exports.tsx, edge_tsx_anon_default.tsx, edge_tsx_mixed.tsx.


File changes

Modified files

File What changed
nowreck/scanner/typescript_scanner.py _get_tsx_language() (lazy language_tsx()); _new_parser(language); scan_ts_file / scan_ts_calls dispatch on .tsx extension; docstrings → TS family
nowreck/scanner/repository_scanner.py _discover_ts_files() matches both *.ts and *.tsx (via itertools.chain); ScanResult.ts_files docstring → TS family
test_milestone1/test_milestone1_checkpoint.py PURE_TSX_REPO, EXPECTED_TSX_FILES, fixture, TestPureTsxRepo class, added to cross-repo determinism + pre/post loops
test_milestone1/demo_milestone1.py Pure TSX repo added to the demo list; TS print line relabeled TS files:
tests/test_change_detector.py TestDetectTsxChanges class (8 tests)
README.md Roadmap: TSX marked done in v0.7.0
docs/nowreck-v7-scope.md Full scope document tracing the increment
docs/release7.md This release notes file

New files

File What it covers
test_milestone1/repos/pure-tsx/src/ New milestone repo: greeter.tsx, calculator.tsx, models.tsx (React-style equivalents of pure-ts)
test_ts_samples/test_phase1_comprehensive_tsx.py 54-test comprehensive TSX suite
test_ts_samples/test_phase1_multiround_tsx.py 36-test, 7-round TSX suite
test_ts_samples/edge_tsx_*.tsx 5 TSX sample files
test_milestone1/live_tsx_hallucination_test.py Live-model TSX DoD test (Phase 4)
docs/nowreck-v7-scope.md Full scope document
docs/release7.md This release notes file

Unchanged

  • _tree_sitter_helpers.py, symbol_index.py, change_detector.py0 changes
  • Claim parser, claim verifier, reporter, CLI, picker — 0 changes
  • JSON output schema — 0 changes
  • Claim types — exactly the same 7
  • .ts / .js / .py scanning behaviour — byte-identical (hard gate)
  • Existing milestone repos (pure-python, pure-js, pure-ts, mixed) — 0 changes
  • Dependencies — 0 new packages

Installing / upgrading

pipx install .    # fresh install from repo
pip install -e .  # or editable install

Requires Python 3.10+. No new dependencies.

nowreck --version
# → nowreck 0.7.0

Definition of Done ✅

  1. A .tsx file with JSX (function components, class components, arrow components, JSX-in-body, handlers) scans to the correct symbols and calls — verified by hand against the source, and nowreck fix --pre <empty> --post <pure-tsx repo> detects the expected changes matching reality.
  2. .ts-only repos produce output byte-identical to v0.6.0 for the same inputs.
  3. The full existing test battery passes, plus the new TSX sample suites and milestone-checkpoint assertions.
  4. ruff: 0 issues, basedpyright: 0 errors.
  5. Live TSX DoD test (real model, induced false claim) passes at release time with the user's key.

Result (verified live): ran the real CLI against the pure-tsx milestone repo (empty pre → post with a real added component WelcomeBanner). 14 hand-written claims → 12 CONFIRMED / 1 CONTRADICTED (the induced false call Farewell → notify, which doesn't exist — correctly caught) / 1 UNVERIFIABLE (GhostComponent, which doesn't exist). Verbose output showed every Matched: block with line_number values cross-checked against the actual .tsx source — all 10 matched definitions exact (e.g. Greeting line 3, formatGreeting line 8, Farewell line 12, WelcomeBanner line 17 of greeter.tsx; Calculator line 3, computeAverage line 30 of calculator.tsx; UserCard line 8, AdminCard line 17, UserList line 31 of models.tsx). All 70 non-verbose output lines preserved verbatim in verbose mode (only the one-line Evidence: / unexplained summaries replaced by detail blocks, per v0.6.0 design). The .ts-only pure-ts repo scans identically (3 files, 16 symbols, 0 failures, extensions strictly .ts).

Live DoD (real model, user's key, nvidia/nemotron-3-ultra-550b-a55b:free): TSX live test PASS ×2 rounds — round 1: 18 claims → 17 CONFIRMED / 1 CONTRADICTED (induced false call caught) / 0 UNVERIFIABLE; round 2: 12 claims → 11/1/0. Identical catch both times.


What's next

The roadmap remains focused on narrow, testable increments, each with its own scope document and phase-by-phase build discipline.

  • explanation field on claims — model + prompt change (README documents it, the Claim model doesn't have it yet) — deferred from v6
  • Scan-summary expansion in verbose mode (per-language file counts) — deferred from v6
  • Interfaces / enums / type aliases as claim types (ADD_INTERFACE / REMOVE_INTERFACE) — still deferred; needs new claim types first
  • TS polish (from v5): abstract methods, constructor parameter properties, decorators — separate polish increment
  • Additional model providers (Anthropic, Gemini)
  • Caching for large repositories
  • CI/CD integration

NoWreck v0.6.0 — Verbose Mode Release

Choose a tag to compare

@AstralXVoid AstralXVoid released this 16 Aug 07:32

NoWreck v0.6.0 — Verbose Mode Release

Release date: August 2026
Previous release: v0.5.0 (TypeScript Support)
Focus: --verbose mode showing full deterministic evidence per claim — the oldest item on the roadmap. A reporter + CLI feature only: zero changes to scanners, the symbol index, the change detector, the claim parser, the verifier, the 7 claim types, or the JSON schema.


What's new in v0.6.0

--verbose mode ✅

The terminal report already showed, per claim, a one-line verdict and a
one-line Evidence: / Reason:. Verbose mode adds full deterministic
detail
for every claim — the exact structural facts the verifier matched:

nowreck fix --pre <pre-snapshot> --post <post-snapshot> --claims '<json>' --verbose

For each CONFIRMED / CONTRADICTED claim, verbose mode shows:

  • Claim: — all eight claim identity fields exactly as report_json
    serializes them: type, symbol_name, file_path, parent_class,
    line_number, caller_name, called_name, confidence (the model's
    original value)
  • Matched: — the complete DetectedChange field dump that confirmed
    or contradicted the claim, including the exact line_number of the
    matched symbol — a structural fact the one-line view hides
  • Confidence: — the display confidence with the same 100%-for-
    structural-match rule as the claim line

For UNVERIFIABLE claims it shows the full claim dump plus the existing
Reason:. Unexplained changes get a full DetectedChange field dump
instead of the one-line summary.

Every field shown is already computed by the pipeline — verbose mode is
a presentation-layer change only. It proves why a verdict was reached by
printing the exact structural fact the verifier matched. Determinism is
unchanged: verbose mode shows more of the same deterministic facts, never
new judgment.

Scope boundary: JSON unchanged

nowreck fix --json already serializes the full matched_change for every
result — it was already "verbose" in machine-readable form. --verbose
does not change JSON output; the CI schema stays frozen. --verbose
and --json together simply behave like --json.

Non-verbose output: byte-identical

The default (non-verbose) rendering is pinned byte-for-byte to the v0.5.0
output. A golden regression test captures the v0.5.0 rendering and asserts
the current default matches it exactly — the hard gate that proves verbose
mode only adds detail.


Test suite growth

Suite v0.5.0 v0.6.0 Growth
pytest (project unit tests) 433 449 +16
JS comprehensive 101 tests 101 tests
JS multi-round 80 tests 80 tests
TS comprehensive 42 tests 42 tests
TS multi-round 29 tests 29 tests
Milestone 1 checkpoint (4 repos) Clean Clean
Phase 4a demo (17 TS claims) Clean Clean
Live hallucination-catch tests (JS + TS) PASS PASS
ruff 0 issues 0 issues
basedpyright 0 errors 0 errors

+16 new pytest tests, broken down as:

  • Phase 1 (plumbing): tests/test_cli.py--verbose parses, defaults
    to False, accepted in both prompt-mode and pre/post-mode paths;
    tests/test_picker.py — both picker flows ask the verbose question,
    answer Yes → fresh verbose reporter for that run only (shared reporter
    never mutated), answer No → v0.5.0 rendering path; tests/test_picker_integration.py
    — happy-path asserts the question is asked once with the right prompt
  • Phase 3 (rendering): tests/test_terminal_reporter.pyTestReporterVerbose
    class (10 tests): full claim field dump, full matched-change dump,
    UNVERIFIABLE claim + reason, unexplained full change dump, None-field
    omission, claim-line byte-identity across modes, Evidence-line
    replacement (not duplication), non-verbose byte-identity to v0.5.0
    (golden gate), determinism across runs, CONTRADICTED matched-change dump

File changes

Modified files

File What changed
nowreck/cli.py --verbose flag on fix (store_true, default False, help notes no-op with --json)
nowreck/reporter/terminal_reporter.py __init__(colour=True, verbose=False); claim/unverifiable/unexplained sections branch on verbose; new _append_verbose_claim_detail + _append_verbose_change_detail helpers
nowreck/main.py Reporter constructed once as TerminalReporter(colour=colour, verbose=args.verbose)
nowreck/picker.py _ask_verbose() helper; both flows (_run_verification, _run_pre_post) ask before rendering; Yes → fresh TerminalReporter(colour=True, verbose=True) per run
tests/test_cli.py 3 new flag tests
tests/test_picker.py 2 new verbose-choice test classes (3 tests) + confirm-mock on 8 existing tests
tests/test_picker_integration.py Happy-path asserts verbose question; confirm-mock on 3 pre_post tests
tests/test_terminal_reporter.py TestReporterVerbose class (10 tests)
README.md Roadmap: --verbose marked done in v0.6.0; TSX marked v0.7.0
docs/nowreck-v6-scope.md Full scope document tracing the increment
docs/release6.md This release notes file

New files

File What it covers
docs/nowreck-v6-scope.md Full scope document (Phase 4 output)
docs/release6.md This release notes file

Unchanged

  • Python / JavaScript / TypeScript scanners — 0 changes
  • Symbol index, change detector, claim parser, claim verifier — 0 changes
  • JSON output schema — 0 changes
  • Claim types — exactly the same 7
  • Non-verbose terminal output — byte-identical (golden-tested)
  • All milestone repos — 0 changes
  • Dependencies — 0 new packages

Installing / upgrading

pipx install .    # fresh install from repo
pip install -e .  # or editable install

Requires Python 3.10+. No new dependencies.

nowreck --version
# → nowreck 0.6.0

Definition of Done ✅

  1. nowreck fix --pre <empty> --post <pure-ts repo> --verbose shows, for a
    hand-written claim set, the full claim identity and the exact
    DetectedChange fields that confirmed/contradicted it — matching
    reality.
  2. nowreck fix ... (without --verbose) output is byte-identical to
    v0.5.0 for the same inputs.
  3. The full existing test battery passes, plus the new verbose tests.
  4. ruff: 0 issues, basedpyright: 0 errors.

Result (verified live): ran the real CLI against the pure-ts milestone
repo (empty pre → full post, 17 hand-written claims covering all 7 claim
types). Verbose output showed every Matched: block with line_number
values cross-checked against the actual source — all 12 definitions
matched exactly (e.g. formatGreeting at line 9 of greeter.ts,
Calculator at line 3 of calculator.ts, AdminUser at line 20 of
models.ts). All 75 non-verbose output lines are preserved verbatim in
verbose mode (only the one-line Evidence: / unexplained summaries are
replaced by detail blocks, per design). Milestone demos pass on all 4
repos; 45/45 milestone checkpoint; full battery green.


What's next

The roadmap remains focused on narrow, testable increments, each with its
own scope document and phase-by-phase build discipline. v0.7.0 is TSX
(.tsx files)
— decided during the v6 planning conversation; it gets its
own scope document when work begins.

  • TSX (.tsx files) — separate TSX grammar + JSX handling — v0.7.0 (decided)
  • explanation field on claims — model + prompt change (README documents
    it, the Claim model doesn't have it yet) — deferred from v6
  • Scan-summary expansion in verbose mode (per-language file counts) —
    deferred from v6; verbose is about claim evidence, not scan statistics
  • Additional model providers (Anthropic, Gemini)
  • Caching for large repositories
  • CI/CD integration

NoWreck v0.5.0 — TypeScript Support Release 🎉🎉

Choose a tag to compare

@AstralXVoid AstralXVoid released this 14 Aug 16:10

NoWreck v0.5.0 — TypeScript Support Release

Release date: August 2026
Previous release: v0.4.0 (JavaScript Polish)
Focus: Adding TypeScript as a first-class language alongside Python and JavaScript — same 7 claim types, same deterministic pipeline, zero changes to the verifier.


What's new in v0.5.0

TypeScript support ✅

NoWreck now scans .ts files with the same structural pipeline it uses for
Python and JavaScript. Everything that works for JS symbols works for TS
symbols — the verifier, change detector, and reporter never need to know
which language produced the data.

Pattern Captured as
function foo() {} FUNCTION foo
const foo = () => {} FUNCTION foo
function* gen() {} FUNCTION gen
async function foo() {} FUNCTION foo
class Foo { bar() {} } CLASS Foo + METHOD bar
export function foo() {} FUNCTION foo (export unwrapped)
export default function foo() {} FUNCTION foo
const x = (function() { ... })() (IIFE) ⛔ Explicitly excluded

Deferred (documented, not built): interfaces, type aliases, enums,
TSX (.tsx) files, decorators, and access modifiers — each has its own
reasoning in docs/nowreck-v5-scope.md.

Shared tree-sitter helpers

The JS scanner's helpers (_unwrap_parens, _is_iife, arrow-declarator
handling, call detection) were language-agnostic — the TypeScript grammar
uses identical node type names for every in-scope pattern. They were
extracted into nowreck/scanner/_tree_sitter_helpers.py and are now shared
by both the JS and TS scanners. This removes ~390 lines of duplication and
makes future language scanners (Rust, Go) even simpler to add.

New dependency

  • tree-sitter-typescript>=0.23.2

Test suite growth

Suite v0.4.0 v0.5.0 Growth
pytest (project unit tests) 388 388
JS comprehensive 101 tests 101 tests
JS multi-round 80 tests 80 tests
TS comprehensive (new) 42 tests +42
TS multi-round (new) 29 tests +29
Milestone 1 (4 repos: py + js + ts + mixed) Clean Clean
Phase 4a demo (17 TS claims) Clean
Live hallucination-catch test (JS) Clean Clean
Live hallucination-catch test (TS, new) PASS (Nemotron 3 Ultra, free)
ruff 0 issues 0 issues
basedpyright 0 errors 0 errors

42 TS comprehensive tests — covering every TS pattern in scope with
positive and negative controls, including a negative test proving that
interfaces, type aliases, and enums are not captured.

29 TS multi-round tests — repeatability (3 identical runs), a 1100-symbol
stress file, path variants, real-world TS patterns, line-number accuracy,
JS regression, and chaos sampling.


File changes

Modified files

File What changed
nowreck/scanner/javascript_scanner.py Import shared helpers from _tree_sitter_helpers.py; removed duplicated local copies
nowreck/scanner/repository_scanner.py ScanResult.ts_files field, _discover_ts_files(), _parse_ts_file(), success_count includes TS
nowreck/scanner/symbol_index.py build() processes ts_files alongside modules and js_files
nowreck/detector/change_detector.py TS files included in file diffs + TS call re-read for CALL_DETECTED
nowreck/picker.py Scan summary shows TS file counts
test_milestone1/test_milestone1_checkpoint.py TestPureTsRepo class + TS in cross-repo determinism
test_milestone1/demo_milestone1.py Shows .ts files in scan output
pyproject.toml Version 0.5.0, new tree-sitter-typescript>=0.23.2 dependency
nowreck/__init__.py Version bump to 0.5.0
nowreck/main.py Banner updated to v0.5.0
README.md Limitations + Roadmap + scan description updated for TS
use.md Version + troubleshooting updated for TS

New files

File What it covers
nowreck/scanner/typescript_scanner.py The TS scanner (scan_ts_file, scan_ts_calls)
nowreck/scanner/_tree_sitter_helpers.py Shared tree-sitter helpers (symbol collection, IIFE detection, call extraction)
test_ts_samples/edge_basic.ts Basic function, arrow, class, method
test_ts_samples/edge_export.ts Export function/class/const-arrow, export default
test_ts_samples/edge_generators.ts Generator/async-generator patterns
test_ts_samples/edge_iife.ts IIFE exclusion patterns
test_ts_samples/edge_types_only.ts Negative test — interfaces/types/enums NOT captured
test_ts_samples/test_phase1_comprehensive.py 42-test comprehensive suite
test_ts_samples/test_phase1_multiround.py 29-test multi-round/stress suite
test_milestone1/repos/pure-ts/ Pure-TypeScript milestone repo (3 files)
test_milestone1/demo_phase4a_ts.py End-to-end pipeline demo on pure-ts repo
test_milestone1/live_ts_hallucination_test.py Definition-of-Done live-model test (needs API key)
docs/nowreck-v5-scope.md Full scope document tracing the increment
docs/release5.md This release notes file

Unchanged

  • Python scanner — 0 changes
  • Claim verifier — 0 changes
  • Claim parser — 0 changes
  • Claim types — exactly the same 7
  • CLI interface, interactive picker structure, configuration
  • All existing milestone repos (pure-python, pure-js, mixed)

Installing / upgrading

pipx install .    # fresh install from repo
pip install -e .  # or editable install

Requires Python 3.10+. TypeScript scanning requires tree-sitter-typescript
(installed automatically with the package).

nowreck --version
# → nowreck 0.5.0

Definition of Done ✅

The v5 Definition of Done — the same live-model hallucination-catch test
used for Python and JS, now on a TypeScript test file — is at
test_milestone1/live_ts_hallucination_test.py. It deliberately induces a
false CALLS_FUNCTION claim (farewell() -> notify(), where notify does
not exist) and expects the verifier to catch it as CONTRADICTED while real
TS symbols confirm.

Result (verified live): run against OpenRouter with the free
nvidia/nemotron-3-ultra-550b-a55b:free model — 20 claims, 19 CONFIRMED,
1 CONTRADICTED, 0 UNVERIFIABLE
. Real TS symbols confirmed; the induced
false call was caught. The JS DoD test passes on the same model, confirming
the shared-helper refactor did not regress v4.

NOWRECK_API_KEY=your-key python test_milestone1/live_ts_hallucination_test.py

What's next

The roadmap remains focused on narrow, testable increments, each with its
own scope document and phase-by-phase build discipline:

  • TSX (.tsx files) — separate TSX grammar + JSX handling
  • --verbose mode showing full deterministic evidence per claim
  • Additional model providers (Anthropic, Gemini)
  • Caching for large repositories
  • CI/CD integration

NoWreck v0.4.0 — JavaScript Polish Release

Choose a tag to compare

@AstralXVoid AstralXVoid released this 29 Jul 14:48

NoWreck v0.4.0 — JavaScript Polish Release

Release date: July 2026
Previous release: v0.3.0 (JavaScript Core)
Focus: Closing three deferred JavaScript gaps: generator functions, export default patterns, and IIFE awareness.


What's new in v0.4.0

Gap 1: Export default patterns ✅

Named default exports (export default function foo() {}, export default class Foo {}) were already working in v3 — the tree-sitter grammar provides a declaration field for these. The original scope doc's assumption that they were dropped was wrong. v0.4.0 adds proper test coverage and fixes a misleading comment that claimed they weren't captured.

No code logic changes were needed — just tests and documentation.

Gap 2: Generator functions ✅

All function* generator patterns are now captured:

Pattern Captured as Previously
function* foo() {} FUNCTION foo ❌ Dropped
async function* bar() {} FUNCTION bar ❌ Dropped
const baz = function*() {} FUNCTION baz ❌ Dropped
export function* qux() {} FUNCTION qux ❌ Dropped
export default function* gen() {} FUNCTION gen ❌ Dropped

What changed: Added generator_function_declaration (for declarations) and generator_function (for expressions) alongside the existing function_declaration and function_expression checks in 6 sites across the scanner.

Gap 3: IIFE awareness ✅

Immediately-invoked function expressions are now explicitly excluded from being captured as symbols, with debug logging so you can see why they were skipped:

Pattern Before v4 After v4
const x = (function() { ... })() ❌ Silently excluded ✅ Explicitly excluded + tested
const x = (() => { ... })() ❌ Silently excluded ✅ Explicitly excluded + tested
(function() { ... })() ❌ Silently excluded ✅ Explicitly excluded + tested
void function() { ... }() ❌ Silently excluded ✅ Explicitly excluded + tested
const normal = () => {} (positive control) ✅ Captured ✅ Still captured

What changed: A new _is_iife() helper, explicit skip logic in both _collect_top_level_symbols and _maybe_arrow_function_declarator, and a latent bug fix in _unwrap_parens where child(0) returned the ( token instead of the inner expression.

Bonus fix: _unwrap_parens latent bug

Found and fixed a bug dating back to v3's JS scanner: child(0) on a parenthesized_expression node returned the ( syntactic token — not the inner expression. Changed to named_child(0), which correctly skips syntactic tokens. The old code worked by accident because ( doesn't match any function type check, but it would have failed for genuinely parenthesized arrow functions like const x = (() => 1).


Test suite growth

Suite v0.3.0 v0.4.0 Growth
pytest (project unit tests) 388 388
JS comprehensive 78 tests 101 tests +23
JS multi-round 80 tests 80 tests
Milestone 1 (3 repos) Clean Clean
Phase 4a demo (14 claims) Clean Clean
Live hallucination-catch test Clean Clean
ruff 0 issues 0 issues
basedpyright 0 errors 0 errors

101 comprehensive tests — covering every JS pattern NoWreck can parse, with positive and negative controls for each.


File changes

Modified files

File What changed
nowreck/scanner/javascript_scanner.py Added generator types (6 sites), _is_iife helper, _unwrap_parens latent bug fix, explicit IIFE skip logic
test_js_samples/edge_export_default.js Updated comments, added export default class Bar with method
test_js_samples/edge_async_generators.js Added generator expression pattern, updated comments
test_js_samples/test_phase1_comprehensive.py +23 tests — export default, generators, IIFEs
test_js_samples/test_phase1_multiround.py Updated round 4 generator assertion
README.md Updated Limitations and Roadmap for v0.4.0
nowreck/__init__.py Version bump to 0.4.0
pyproject.toml Version bump to 0.4.0
nowreck/main.py Banner updated to v0.4.0
nowreck/reporter/terminal_reporter.py Docstring updated to v0.4.0

New files

File What it covers
test_js_samples/edge_generators.js All generator patterns (declaration, async, expression, export, export default, positive/negative controls)
test_js_samples/edge_iife.js All IIFE patterns (const, arrow, standalone, void, var, positive controls)
docs/release4.md This release notes file
docs/nowreck-v4-scope.md Full scope document tracing the increment

Unchanged

  • All milestone repos (test_milestone1/)
  • Symbol index, change detector, claim parser, claim verifier, reporter
  • CLI interface, interactive picker, configuration
  • Python scanner — 0 changes
  • No new dependencies

Installing / upgrading

pipx install .    # fresh install from repo
pip install -e .  # or editable install

Requires Python 3.10+. JavaScript scanning requires tree-sitter-javascript (installed automatically with the package via optional dependency).

nowreck --version
# → nowreck 0.4.0

What's next

The roadmap remains focused on narrow, testable increments:

  • --verbose mode showing full deterministic evidence per claim
  • Additional model providers (Anthropic, Gemini)
  • Caching for large repositories
  • TypeScript support — likely the next major language increment
  • CI/CD integration

Each increment gets its own scope document, its own phase-by-phase build discipline, and its own human-checked checkpoints.

NoWreck v0.3.0 — JavaScript Support 🎉

Choose a tag to compare

@AstralXVoid AstralXVoid released this 29 Jul 10:21
4feefdc

NoWreck v0.3.0 — JavaScript Support 🎉

Deterministic verification for AI code changes — now for JavaScript too.

Python
License: FSL-1.1-MIT

What's new in v0.3.0

The headline feature is JavaScript support — NoWreck can now scan, parse, and verify JavaScript files alongside Python files in the same repository. This is the first time the pipeline has been extended beyond Python, and it's designed so that adding future languages follows the same pattern.

JavaScript scanning via Tree-sitter

JavaScript files (.js) are now parsed using Tree-sitter with the tree-sitter-javascript grammar, producing the same Symbol / SymbolType data shapes as the Python parser. The rest of the pipeline — change detection, claim verification, and reporting — never knows or cares which language produced the data.

What the JS scanner captures:

Pattern Example Status
Function declarations function greet() {}
Arrow functions (assigned) const greet = () => {}
Classes class Calculator {}
Class methods add(a, b) { ... }
export function export function greet() {}
export class export class Calculator {}
export const (arrow) export const greet = () => {}
Function calls greet() in function bodies ✅ (simple calls only)

Mixed-language repos

NoWreck handles repositories with both .py and .js files in a single scan. The pre/post summaries show separate file counts for each language:

Scan Summary
────────────
Python:    5 files (3 success, 0 failed)
JavaScript: 3 files (3 success, 0 failed)
Symbols:   22 total (12 functions, 4 classes, 6 methods)

Same 7 claim types — unchanged

No new claim types were added. The same 7 deterministic claims work across both languages:

  • ADD_FUNCTION / REMOVE_FUNCTION
  • ADD_CLASS / REMOVE_CLASS
  • FILE_CREATED / FILE_DELETED
  • CALLS_FUNCTION

A claim about a Python function and a claim about a JavaScript function are verified identically — the verifier doesn't need to know which language produced the data.

Lazy dependency loading

The tree-sitter-javascript dependency is loaded lazily — it's only imported when a JavaScript file is actually scanned. This means:

  • Pure-Python repos work without tree-sitter-javascript installed
  • No cascading import failures in the Python-only test suite
  • All 388 existing pytest tests pass without the JS grammar

Full changelog

Added

  • New module: nowreck/scanner/javascript_scanner.py — Tree-sitter-based JavaScript parser with lazy grammar loading
    • scan_js_file(path) — parses a .js file and returns list[Symbol]
    • scan_js_calls(source_code, symbols) — extracts call_expression nodes and returns list[DetectedChange] for CALL_DETECTED
    • _get_js_language() — lazy-loads tree-sitter-javascript with double-checked caching
  • SymbolIndex.js_symbols property — returns only JavaScript symbols (those without an ast module origin)
  • SymbolIndex.by_name(name) — language-agnostic lookup (finds symbols across both languages)
  • RepositoryScanner extended — discovers .js files, routes them to javascript_scanner, populates ScanResult.js_files
  • ChangeDetector.detect() extended — extracts JS call_expression nodes alongside Python ast.Call walking
  • TerminalReporter extended — shows Python vs JS file counts and language-specific symbol breakdowns in scan summaries
  • _strip_markdown_fence() in claims/parser.py — handles ```json...``` from model output

Changed

  • Bumped version from v0.2.0 → v0.3.0
  • Updated pyproject.toml — added tree-sitter-javascript>=0.25 dependency
  • Updated .gitignore — added _binary_test.bin under test artifacts
  • Updated README.md — JS integration documented in scan stage, limitations, roadmap, troubleshooting, and tips
  • Updated use.md — version references, JSON schema examples
  • Fixed pre-existing ruff issues in tests/test_picker.py and tests/test_picker_integration.py (unused imports, line lengths)
  • Fixed pre-existing type errors in nowreck/picker.py (missing questionary stub)
  • Fixed ordering-sensitive flaky test (test_empty_prompt_flow) in test_picker_integration.py

Known limitations (v0.3.0)

  • Generator functions (function*) — not captured (deferred)
  • export default — not captured (deferred)
  • IIFEs — not captured (deferred)
  • TypeScript — not yet supported (separate scope, deferred)
  • Attribute calls (e.g., console.log(), obj.method()) — excluded from CALLS_FUNCTION detection; only simple name() calls are tracked
  • All existing Python limitations still apply (no dynamic behavior, no cross-file resolution beyond direct name matching, no semantic analysis)

Test statistics

Suite Tests Result
Python unit tests (pytest) 388 ✅ 388/388 pass
JS multi-round (repeatability, stress, chaos) 80 ✅ 80/80 pass
JS comprehensive (core, edge cases, negatives, error handling) 78 ✅ 78/78 pass
Milestone 1 — pure Python repo 10 ✅ Deterministic (3x)
Milestone 1 — pure JS repo 10 ✅ Deterministic (3x)
Milestone 1 — mixed repo 10 ✅ Deterministic (3x)
Full pipeline determinism (mixed repo, 5 runs) 1 ✅ Identical every run
Phase 4a end-to-end demo (14 hand-written claims) 14 ✅ Pipeline clean
Phase 4d live-model hallucination-catch (real API) 1 ✅ Hallucination caught
Total ~590 ✅ All pass
Linting (ruff) ✅ 0 issues
Type checking (basedpyright) ✅ 0 errors, 0 warnings, 0 notes

How it works

┌─────────────────────────────────────────────────────────┐
│                   Prompt mode                           │
│                                                         │
│  Your prompt ──► AI model ──► diff + claims             │
│                                   │                     │
│                                   ▼                     │
│  Pre-scan ──► Symbol index ──► Change Detector          │
│  Post-scan ──► Symbol index ────────┘                   │
│                                         │               │
│  Claims ──► Claim Verifier ◄────────────┘               │
│                  │     pure comparison — no AI judgment  │
│                  ▼                                      │
│          Verification Report                            │
│   ✓ CONFIRMED  ✗ CONTRADICTED  ? UNVERIFIABLE           │
└─────────────────────────────────────────────────────────┘

Scan stage (now with dual-language support)

  1. Discover — recursively finds .py and .js files in both snapshots
  2. Parse — routes each file to the correct parser:
    • .py → Python's built-in ast module
    • .js → Tree-sitter with tree-sitter-javascript grammar
  3. Index — builds a unified SymbolIndex from both languages

Both parsers produce identical Symbol / SymbolType data shapes (using LanguageAdapter patterns anticipated in earlier architecture). The rest of the pipeline is language-agnostic.


Quick start with JavaScript

# Create a JS test repo
mkdir -p /tmp/js-app/pre /tmp/js-app/post

cat > /tmp/js-app/pre/greeter.js << 'EOF'
function greet(name) {
  return "Hello, " + name + "!";
}
EOF

cat > /tmp/js-app/post/greeter.js << 'EOF'
function greet(name) {
  return "Hello, " + name + "!";
}

const farewell = (name) => "Goodbye, " + name + "!";
EOF

# Detect changes
nowreck fix --pre /tmp/js-app/pre --post /tmp/js-app/post

# Or with claims that include a hallucinated call
nowreck fix \
  --pre /tmp/js-app/pre \
  --post /tmp/js-app/post \
  --claims '{
    "claims": [
      {
        "type": "ADD_FUNCTION",
        "symbol_name": "farewell",
        "file_path": "greeter.js",
        "confidence": 0.99,
        "explanation": "Added farewell arrow function."
      },
      {
        "type": "CALLS_FUNCTION",
        "symbol_name": "farewell",
        "file_path": "greeter.js",
        "caller_name": "farewell",
        "called_name": "notify",
        "confidence": 0.85,
        "explanation": "farewell calls notify to send the message."
      }
    ]
  }'

# Expected: ADD_FUNCTION CONFIRMED, CALLS_FUNCTION CONTRADICTED
# (farewell exists, but it doesn't call notify)

Mixed Python + JavaScript

nowreck fix --pre ./before --post ./after
# → Shows Python: 3 files, JavaScript: 2 files in scan summary

Design decisions

Why Tree-sitter?

JavaScript has no equivalent of Python's built-in ast module, so an external parser was required. Tree-sitter was chosen because:

  • Mature JS grammar — well-maintained tree-sitter-javascript with broad coverage
  • Reusable pattern — same parser family would be used for Go, Rust, etc.
  • Concrete syntax trees — provides real source positions for accurate claim-to-diff line mapping

Why lazy imports?

The tree-sitter-javascript grammar is imported lazily (only when a .js file is actually scanned). This ensures:

  • The Python-only test suite doesn't cascade-fail on import
  • Pure-Python repos work without the JS grammar installed
  • The dependency is a hard install requirement (in pyproject.toml) but a soft runtime requirement

Why no new claim types?

The existing 7 claim types (ADD_FUNCTION, REMOVE_FUNCTION, ADD_CLASS, REMOVE_CLASS, FILE_CREATED, FILE_DELETED, CALLS_FUNCTION) are language-agnosti...

Read more

v0.2.0 - Interactive Terminal Picker

Choose a tag to compare

@AstralXVoid AstralXVoid released this 21 Jul 13:30

What's new

  • Added nowreck --interactive — a menu-driven interface for setting up config, running verification, and viewing reports without typing full commands and flags.
  • Existing CLI commands (nowreck fix, nowreck config) are unchanged and remain the primary interface — the picker is an additional entry point, not a replacement.

Notes

  • No changes to core verification logic — the picker calls the exact same pipeline as the CLI.
  • Full v2 design rationale: see docs/nowreck-v2-scope.md