Releases: yigitcan-ozturk/bidlint
Release list
bidlint v1.1.0
bidlint v1.1.0
BidLint 1.1.0 completes the production-adoption milestone while preserving the frozen BidLint 1.x compliance semantics.
Production-adoption controls
- offline BidLint 1.x report conformance validation and compatibility manifest
- private-first external-pilot workspace and evidence-retention protocol
- non-leaking pilot sanitization scanner for contact, commercial, metadata, hidden-content and XLSX leakage signals
- manifest-driven repeated pilot execution with deterministic output and corpus SHA-256 evidence
- immutable approved-baseline replay verification with
bidlint-pilot-verify - explicit
bidlint-pilot-gaterequiring clean sanitization, deliberate human/domain approval, reviewed non-PASS findings, manual specification-scope disposition when required, zero unresolved limitations and exact baseline replay - conservative XLSX specification requirement blocks with independent worksheet selection and explicit unscoped-row coverage evidence
- production-shaped conflict-path CPU and peak-memory profiling gate
- validated wheel artifact retention for isolated private-pilot replay
- fail-closed stable-release workflow that refuses stale or premature tags pointing at a different release commit
Correctness hardening derived from the external pilot
- empty external pilots cannot pass with zero evaluated requirements
- Grade/designation values such as Grade 304 and A15 stay qualitative rather than becoming accidental numeric thresholds
- composite dimensions remain qualitative until deterministic multidimensional comparison is supported
- standard OOXML schema URLs no longer create sanitization URL false positives
- unrelated fuzzy parameter names without lexical overlap require stronger evidence before matching
- commercial XLSX values hidden behind currency number formats are detected by the sanitization scanner
- structured XLSX rows outside the supported contiguous requirement block are surfaced as explicit manual-scope evidence rather than silently treated as covered
External sanitized pilot gate
Issue #39 completed the release-evidence gate using a real external drainage-schedule-derived private sanitized corpus.
Final approved replay evidence:
- reviewer:
yigitcan-ozturk - review date:
2026-08-22 - decision:
APPROVE_BASELINE - sanitization:
automated_clear=true,0blockers,0review findings - evaluated requirements:
6 - findings:
5 REVIEW,1 MISSING,0 PASS,0 DEVIATION - deterministic:
true - conformant:
true - manual XLSX scope:
35unscoped populated rows (header + 34 item rows), explicitly human-reviewed - false positives:
0 - false negatives:
0 - unresolved limitations:
0 - known product defects:
0 - approved baseline replay: exact match,
0mismatches - final gate:
release_ready=true,failure_count=0
Final reconstructed private evidence digests:
- manifest SHA-256:
68f165a2f2a27df5ba927e52f098c743b2687f8321d8fda252569ebd195dc97f - corpus SHA-256:
93d5738fb2f5b660e940c5a2843bf40416e09c2f5480a735b048455152541e18 - baseline/replay output SHA-256:
759e2b510a2dd6629f23874f656fd301fafb0201b30f15cdd1cd85ae7b6f2084
Raw external/customer documents and the private approval/evidence workspace are not committed to the public repository.
Compatibility boundary
This release does not change the frozen BidLint 1.x PASS / DEVIATION / MISSING / REVIEW semantics or deterministic scoring contract. BidLint does not perform commercial scoring, contractual acceptance or inferred knockout acceptance. External-pilot approval is software baseline/release evidence, not supplier compliance acceptance.
Validation required before merge
The release PR must pass:
- Ruff and pytest on Python 3.11, 3.12 and 3.13
- wheel/sdist build, twine check, installed CLI smoke and
pip check - runtime dependency audit
- deterministic 20k-fact benchmark
- production-shaped conflict-path CPU and peak-memory profile
The stable v1.1.0 tag and GitHub Release must only be created from the final merged release commit. The stale/premature v1.1.0 release and tag from the invalidated earlier release sequence were removed before this release branch was prepared.
bidlint v1.0.0
bidlint v1.0.0
Released 2026-08-21.
BidLint 1.0.0 is the first stable-contract release of the deterministic technical bid compliance engine.
Stable compatibility contract
The 1.x line now has an explicit compatibility floor covering:
- public CLI commands and process exit codes;
- report JSON required keys;
SourceRef,Requirement,VendorFact, andFindingrequired fields;PASS / DEVIATION / MISSING / REVIEWfinding semantics;- knockout status semantics;
- deterministic compliance-score behavior;
- semantic-versioning and backward-compatibility policy.
The machine-readable contract is available through bidlint.contracts.stable_contract_manifest() and is protected by regression tests.
Procurement workflow
The stable release includes the v0.8 procurement workflow:
- explicit technical knockout criteria;
- bidder clarification and unanswered requirement registers;
- deviation and internal review queues;
- procurement-ready ranking;
- procurement-aware supplier-scorecard contract v2.
No commercial scoring, price preference, contractual acceptance, or implicit knockout inference is introduced.
Production hardening
The v0.9 hardening work is included in 1.0.0:
- stable CLI error categories and exit codes;
- malformed/adversarial PDF, XLSX, and IFC regression coverage;
- wheel/sdist build and smoke-install validation on Python 3.11, 3.12, and 3.13;
- runtime dependency security audit;
- deterministic large-package benchmark with repeated output-digest verification.
The CI benchmark exercises 20,000 input facts and requires deterministic consolidation output under a deliberately broad regression ceiling.
Compatibility
BidLint 1.0.0 supports Python 3.11, 3.12, and 3.13.
Within the 1.x line, patch releases are intended for compatible fixes and minor releases may add backward-compatible surfaces. Removing, renaming, or semantically repurposing frozen contract elements requires a new major version.
See docs/STABLE_CONTRACT.md for the full compatibility policy.
bidlint v0.7.0
bidlint v0.7.0
Released: 2026-08-20
v0.7.0 moves bidlint from single vendor-document comparison toward deterministic real-world bid intake. A supplier submission can now be treated as a multi-document evidence package while preserving the existing rule that uncertainty, source disagreement and hidden precedence must never become automatic technical decisions.
Highlights
Multi-document vendor packages
A vendor input may be a directory containing supported direct-child PDF, XLSX and explicitly scoped IFC evidence:
Supplier-A/
├── compliance-schedule.xlsx
├── pump-datasheet.pdf
├── technical-offer.pdf
└── model.ifc
The package enters the same VendorFact and deterministic compliance pipeline used by direct vendor files.
Equivalent facts across documents collapse deterministically, including compatible engineering-unit conversions. Conflicting evidence is preserved as an explicit provenance-rich REVIEW condition instead of choosing a source silently.
Explicit document classification
Every direct-child package file is assigned a visible document class:
specificationdatasheetcompliance-scheduletechnical-offerignored
Classification uses deterministic filename rules plus exact programmatic overrides. Copied employer specifications and ignored/commercial material do not become vendor technical evidence.
Unsupported file types remain visible as ignored package documents rather than being parsed or guessed.
Explicit evidence priority
Packages may opt into an ordered evidence-priority policy across technical document classes.
package = parse_vendor_package(
"Supplier-A",
evidence_priority=(
"compliance-schedule",
"technical-offer",
"datasheet",
),
)No priority exists by default. Without an explicit policy, conflicting facts continue to produce REVIEW.
Priority only narrows a parameter group to the highest available configured class. It never breaks a disagreement between two documents in the same highest-priority class; those conflicts still require review.
Project terminology aliases participate in consolidation
The existing project-specific alias mapping now applies before package duplicate/conflict consolidation as well as during requirement matching.
{
"supplier rated output": "motor power"
}This allows vendor-specific nomenclature in different package documents to resolve to the same canonical parameter before evidence consistency is evaluated.
Aliases do not introduce fuzzy grouping, hidden source precedence or additional confidence.
Mixed-package ranking selector scoping
rank can mix direct files and package directories while using IFC/XLSX selector options.
Selector validation looks inside package directories only at evidence-classified files. IFC selectors are applied only to direct IFC inputs and packages containing evidence IFC files; --xlsx-sheet is applied only to direct XLSX inputs and packages containing evidence XLSX files.
This prevents a global selector from invalidating unrelated PDF-only suppliers in the same ranking run.
Package-level evidence audit
VendorPackage.evidence_audit records how every parsed technical fact was treated during consolidation.
Each audit entry preserves:
- canonical parameter
- original
VendorFactand provenance - document class
- disposition:
selected,equivalent-duplicate,conflictorlower-priority - explicit priority rank when applicable
VendorPackage.to_audit_dict() exposes a JSON-ready package audit containing document classifications, ignored documents, priority policy, raw evidence dispositions, consolidated facts and conflict facts.
The evaluator contract remains unchanged; the audit surface adds traceability rather than a second decision engine.
Sanitized regression packages
The release includes generated multi-document regression fixtures for five engineering families:
- pump: alias-aware equivalent evidence across PDF/XLSX documents
- motor: explicit compliance-schedule priority over conflicting lower-priority evidence
- valve: unresolved disagreement inside the same highest-priority class
- HVAC: aliasing, engineering-unit conversion, copied-specification exclusion and ignored commercial material
- electrical: equivalent evidence alongside an unprioritized technical conflict
Fixtures are synthetic and vendor-neutral. Tests generate temporary PDF and formula-free XLSX files and run the normal parsers rather than replacing extraction with mocks.
Existing safety boundaries remain in force
v0.7.0 does not weaken earlier input constraints:
- XLSX formulas, VBA/macros, external relationships, hidden evidence worksheets, merged cells and ambiguous layouts remain rejected
- IFC evidence still requires explicit element scope through the existing IFC selection rules
- unsupported package files are not interpreted as technical evidence
- copied specification documents are not allowed to satisfy vendor requirements
- file type alone never establishes authority
- source disagreement never becomes an automatic PASS or DEVIATION
Validation
The v0.7 branch is covered by GitHub Actions on Python 3.11, 3.12 and 3.13 with Ruff and pytest, including regression coverage for:
- deterministic package discovery
- document classification and overrides
- unit-aware equivalent evidence consolidation
- conflict-to-
REVIEWbehavior - explicit evidence-priority policy and same-class tie handling
- project alias threading through CLI package intake
- mixed PDF/XLSX/IFC package selector scoping
- package-level evidence audit dispositions and provenance
- generated pump, motor, valve, HVAC and electrical multi-document packages
Deliberate limits
This release keeps package intake intentionally conservative:
- only direct-child package documents are considered
- document-class overrides are currently a programmatic surface rather than a package manifest or dedicated CLI policy file
- evidence priority is explicit and opt-in; no hidden default hierarchy is inferred
- package intake does not add commercial or price scoring
- the deterministic requirement matcher and compliance evaluator remain authoritative
v0.7.0 keeps the project rule unchanged: evidence before confidence.
bidlint v0.6.0
bidlint v0.6.0
Released: 2026-08-20
v0.6.0 adds deterministic XLSX vendor-input support to the existing technical-compliance engine. Explicit spreadsheet offer tables can now enter the same VendorFact model used by PDF and IFC evidence without adding a spreadsheet runtime dependency or weakening the evidence-first boundary.
Highlights
XLSX vendor inputs
A formula-free vendor offer workbook can now be compared directly with a specification:
bidlint compare specification.pdf supplier-offer.xlsxThe selected worksheet must expose one explicit parameter column and one explicit offered-value column. Unit and section columns are optional.
For workbooks with more than one visible worksheet, select the evidence sheet explicitly:
bidlint compare specification.pdf supplier-offer.xlsx \
--xlsx-sheet "Technical Offer"The same XLSX adapter is available through extract and rank.
bidlint extract supplier-offer.xlsx --kind vendor \
--xlsx-sheet "Technical Offer"Mixed vendor ranking can combine supported PDF, XLSX and explicitly scoped IFC inputs:
bidlint rank specification.pdf vendor-a.pdf vendor-b.xlsx vendor-c.ifc \
--xlsx-sheet "Technical Offer" \
--ifc-guid 1AbCdEfGhIjKlMnOpQrStuEvidence provenance
Every accepted spreadsheet row becomes a normal VendorFact and preserves:
- workbook filename
- worksheet row number
- selected worksheet name
- optional row section/category/system context
A source section can therefore identify evidence such as:
XLSX:Technical Offer/Electrical
After extraction, the existing terminology matcher, engineering-unit conversion and deterministic compliance evaluator remain authoritative.
Spreadsheet safety boundary
The workbook is treated as evidence, not executable logic.
v0.6.0 deliberately rejects structures that would require calculation, hidden state or positional guessing:
- formulas
- VBA/macros
- external workbook relationships
- hidden evidence worksheets
- merged cells in the selected worksheet
- multiple visible worksheets without explicit
--xlsx-sheetselection - duplicate or ambiguous parameter/offered headers
- incomplete evidence rows containing only a parameter or only an offered value
- conflicting units between the offered cell and an explicit unit column
Boolean cells remain qualitative TRUE / FALSE evidence rather than being converted into numeric 1 / 0 compliance values.
The parser does not recalculate workbooks, follow links, unhide worksheets or reconstruct merged spreadsheet layouts.
Dependency model
XLSX input is parsed directly from OOXML using the Python standard library.
The standard installation remains:
pip install bidlintNo Excel, LibreOffice, openpyxl or other spreadsheet runtime is required for XLSX input or existing XLSX technical-bid output.
Optional integrations remain separate:
pip install 'bidlint[ifc]'
pip install 'bidlint[mcp]'Existing deterministic core remains authoritative
Specification PDF ──> Requirement ───────────────────────────────┐
│
Vendor PDF ─────────> VendorFact ────────────────────────────────┤
Vendor XLSX ────────> explicit OOXML adapter ─────> VendorFact ─┤
Selected IFC ───────> property adapter ───────────> VendorFact ─┤
▼
terminology matcher
│
▼
unit-aware evaluator
│
▼
PASS / DEVIATION / MISSING / REVIEW
XLSX support adds a new evidence adapter, not a new decision engine.
Validation
The stable release is covered by GitHub Actions on Python 3.11, 3.12 and 3.13, including regression coverage for:
- explicit header discovery
- visible worksheet selection
- row and section provenance
- numeric and qualitative values
- boolean preservation
- explicit engineering units
- formula rejection
- macro and external-link rejection
- merged-cell rejection
- ambiguous worksheet/header rejection
- CLI
extract,compareandrankdispatch - coexistence with existing PDF and IFC workflows
Deliberate limits
This release does not:
- infer spreadsheet formulas
- execute spreadsheet code
- follow external workbook links
- guess hidden evidence
- reconstruct merged worksheets
- choose among multiple visible evidence sheets without an explicit selection
- replace the existing deterministic matcher or evaluator
- add commercial or price scoring to bidlint
v0.6.0 keeps the project rule unchanged: evidence before confidence.
bidlint v0.5.0
bidlint v0.5.0
Released: 2026-08-20
v0.5.0 completes the engineering-ecosystem milestone around the deterministic compliance core. It adds explicitly scoped IFC vendor-property inputs, a safe technical-compliance hand-off to supplier-scorecard, and native .xlsx technical bid tabulation.
Highlights
IFC property inputs
Vendor evidence can now come from a local IFC file as well as a PDF.
IFC support is optional:
pip install -e '.[ifc]'Select one vendor element explicitly by GlobalId:
bidlint compare specification.pdf equipment.ifc \
--ifc-guid 1AbCdEfGhIjKlMnOpQrStuOr use an IFC class when the class resolves to exactly one element:
bidlint extract equipment.ifc --kind vendor \
--ifc-class IfcPump \
--ifc-pset Pset_PumpCommonSelected scalar property-set values become ordinary VendorFact records and then flow through the existing terminology matcher, unit conversion and deterministic evaluator.
Safety rules include:
- IFC scope is mandatory
- multi-element class selections are rejected instead of mixed
- complex/list values are skipped
- geometry is not evaluated
- scalar numeric primitives remain unitless unless the source value explicitly includes a unit
- provenance is preserved as
IfcClass:GlobalId/Pset
See docs/IFC.md.
supplier-scorecard technical-compliance contract
A single-vendor comparison can emit a versioned JSON hand-off for the companion supplier-scorecard project:
bidlint compare specification.pdf vendor-a.pdf \
--supplier-name "Supplier A" \
--scorecard-output supplier-a-technical.jsonWhen every finding is deterministically resolved as PASS, DEVIATION or MISSING, the fragment includes bidlint's existing 0–100 compliance score as technical_compliance.
If any finding remains REVIEW, the integration deliberately emits:
{
"technical_compliance": null,
"technical_compliance_status": "REVIEW_REQUIRED"
}This prevents an incomplete technical review from becoming a misleading procurement ranking input. The detailed bidlint report remains the authoritative technical audit.
See docs/SUPPLIER_SCORECARD.md.
Excel technical bid tabulation
Multi-vendor ranking now supports native .xlsx output:
bidlint rank specification.pdf vendor-a.pdf vendor-b.pdf \
--output technical-tabulation.xlsxThe workbook contains:
Ranking— vendor order, compliance scores and status countsMatrix— requirement-by-vendor review matrix with status-specific fillsAudit— long-form evidence, confidence, source page/section and deterministic reason
The workbook uses frozen panes, autofilters, wrapped text and fixed readable widths. It contains no formulas, macros or external links.
The OOXML package is generated with the Python standard library, so the base package gains no spreadsheet runtime dependency. Fixed ZIP timestamps also make identical report data and bidlint version produce byte-identical workbook output.
Existing deterministic core remains authoritative
v0.5.0 does not create new decision engines for IFC, procurement integration or spreadsheets.
PDF / selected IFC property evidence
│
▼
Requirement / VendorFact
│
▼
terminology matcher
│
▼
unit-aware evaluator
│
▼
PASS / DEVIATION / MISSING / REVIEW
│
┌───────┼───────────┐
▼ ▼ ▼
JSON/HTML XLSX supplier-scorecard
The ecosystem adapters consume deterministic results; they do not override them.
Dependency model
The standard installation remains lightweight:
pip install bidlintOptional integrations remain separate:
pip install 'bidlint[mcp]'
pip install 'bidlint[ifc]'XLSX export requires no additional package.
Validation
The release is covered by the existing Python 3.11, 3.12 and 3.13 CI matrix plus regression tests for:
- IFC scalar extraction, ambiguity rejection and provenance
- PDF/IFC deterministic comparison
- supplier-scorecard READY / REVIEW_REQUIRED / NO_REQUIREMENTS contracts
- CLI integration output behavior
- OOXML package structure and worksheet ordering
- XLSX ranking, matrix and audit evidence
- deterministic workbook bytes
rank --output .xlsx
Deliberate limits
This release does not:
- perform IFC geometry compliance
- guess which of multiple IFC elements represents a vendor offer
- infer engineering units missing from IFC values
- turn
REVIEWinto a procurement score - add commercial or price logic to bidlint
- hide workbook calculations in formulas
- change the existing deterministic ranking order
v0.5.0 completes the published roadmap while preserving the core rule: evidence before confidence.
bidlint v0.4.0
bidlint v0.4.0
Released: 2026-08-20
v0.4.0 exposes the deterministic bidlint core through an optional local MCP server and adds a persistent, pollable job lifecycle for larger document operations.
Highlights
Local MCP server
Install the optional MCP integration with:
pip install -e '.[mcp]'Run the stdio server with:
bidlint-mcpThe synchronous MCP tool surface includes:
extractcompareexplain
These tools call the same deterministic PDF parsers, terminology matcher, engineering-unit conversion and compliance evaluator used by the CLI.
Filesystem sandbox
MCP document and alias paths are constrained to BIDLINT_MCP_ROOT, or to the server working directory when the variable is not set.
The server rejects:
- parent traversal outside the configured root
- absolute paths outside the root
- symlinks that resolve outside the root
- unexpected document/alias file types
The MCP server does not fetch remote URLs.
Pollable long-running jobs
Large extraction/comparison work can be submitted through:
submit_extractsubmit_compare
and inspected through:
job_statusjob_resultcancel_job
Job records and terminal results are stored atomically under:
<BIDLINT_MCP_ROOT>/.bidlint/jobs
The in-process worker pool defaults to two workers and can be configured from 1 to 8 with BIDLINT_MCP_JOB_WORKERS.
Running jobs use cooperative cancellation. If the server process stops, previously queued/running jobs are not silently resumed; they are marked failed with an explicit restart error when the job manager starts again.
MCP Tasks-extension boundary
The job lifecycle is deliberately implemented as explicit bidlint tools rather than claiming native MCP Tasks support before the Python MCP SDK exposes a supported server API for that extension.
The internal job manager is kept separate from the MCP adapter so a future native Tasks integration can reuse the same deterministic lifecycle and persistence model.
No second decision engine
MCP does not add another compliance authority. Clients cannot supply a status and have bidlint trust it.
Both synchronous and queued MCP paths still produce PASS / DEVIATION / MISSING / REVIEW through the existing deterministic evaluation layer.
Safety boundary
v0.4.0 deliberately does not:
- expose a network/HTTP server by default
- fetch remote documents
- bypass
BIDLINT_MCP_ROOT - force-terminate a running parser thread
- silently resume interrupted work after restart
- claim native MCP Tasks-extension compatibility through a custom wire-protocol implementation
- change the deterministic compliance rules established by previous releases
See docs/MCP.md for setup, tool contracts and lifecycle details.
bidlint v0.3.0
bidlint v0.3.0
Released: 2026-08-20
v0.3.0 adds a provider-neutral boundary for optional AI-assisted or external structured extraction while keeping the deterministic compliance engine authoritative.
Highlights
Replaceable extraction providers
Optional integrations can implement the StructuredExtractor protocol and return structured requirement or vendor-fact candidates. The core package does not depend on a specific model vendor, SDK, API key or network service.
Evidence before provider confidence
Every provider candidate must include confidence plus source evidence. Before a candidate can enter the deterministic core, bidlint verifies:
- confidence is finite and within
[0, 1] - confidence meets the configured minimum threshold
- the declared source page exists
- the evidence snippet actually occurs on that PDF page after whitespace normalization
- the candidate type matches specification/vendor extraction
- numeric requirement fields are structurally consistent
Rejected candidates remain outside compare() and are returned with explicit rejection reasons.
Deterministic evaluation remains authoritative
Provider confidence is extraction confidence only. It does not become the compliance confidence and it cannot emit PASS, DEVIATION, MISSING or REVIEW.
Validated candidates are converted to the existing Requirement and VendorFact models. The existing terminology matcher, engineering-unit conversion and deterministic evaluator then produce the final findings.
Provider contract
A provider implements:
class MyExtractor:
name = "my-provider"
def extract(self, document: Path, kind: ExtractionKind) -> ExtractionBatch:
...Use extract_with_provider() to invoke and validate an adapter, or validate_extraction() when a structured batch is already available.
See docs/AI_EXTRACTION.md for the full contract.
No new runtime AI dependency
The standard installation still requires no LLM SDK and makes no automatic external AI calls. The deterministic PDF parser and all existing CLI workflows continue to work unchanged.
Safety boundary
v0.3.0 deliberately does not:
- bundle a model/provider implementation
- allow model output to set compliance status
- treat high provider confidence as proof of engineering correctness
- introduce model-defined comparison operators or unit rules
- solve OCR/image interpretation automatically
This release establishes an auditable integration boundary for future optional providers without weakening the deterministic decision model.
bidlint v0.2.2
bidlint v0.2.2
Released: 2026-08-20
v0.2.2 hardens deterministic vendor-datasheet parsing for advanced but explicitly evidenced table layouts. The release expands document coverage without changing the core rule: ambiguous layout evidence is skipped instead of guessed.
Highlights
Coordinate-aligned sparse rows
Recognized tables can now recover rows whose intermediate cells are visually blank when the parameter and offered values align closely with explicit header anchors.
- blank intermediate cells no longer shift the offered value into the wrong semantic column
- blank
Unitcells remain unitless - fragments near column boundaries are rejected rather than assigned by proximity alone
Explicit merged-cell geometry
The positioned-text pass also captures explicit axis-aligned PDF rectangle (re) geometry.
- merged intermediate cells can be recognized when
ParameterandOfferedremain distinct cell boxes - text inside an intermediate merged cell is not split into fabricated
Unit/Requiredvalues - merges touching
ParameterorOfferedare rejected - rotated/skewed rectangles and arbitrary line grids remain unsupported
Repeated explicit header groups
Side-by-side technical tables can now be parsed when each visual group repeats its own parameter-like and offered/value headers.
Parameter Unit Offered Parameter Unit Offered
Motor power kW 11 Flow rate m3/h 125
Each complete row produces one fact per explicit group. Incomplete repeated rows are skipped as a whole rather than partially reconstructed.
Safer Item / Description tables
When a header contains both Item and Description before the offered/value column, Description is preferred as the parameter field because it is the nearest parameter-like header to the offered evidence.
Safety boundary
v0.2.2 still does not:
- OCR scanned/image-only PDFs
- infer arbitrary line-segment grids as table cells
- split semantic values out of merged intermediate cells
- guess multi-column group boundaries when explicit repeated headers are absent
- accept coordinate fragments that fall too close to a column boundary
Validation
All changes are covered by synthetic positioned/boxed PDF regressions and the project CI matrix on Python 3.11, 3.12 and 3.13 with Ruff and pytest.
bidlint v0.2.1
bidlint v0.2.1
Released: 2026-08-20
v0.2.1 hardens bidlint for more realistic engineering datasheets and larger multi-vendor review workflows while keeping the deterministic decision model conservative.
Highlights
Layout-aware vendor PDF parsing
- preserves horizontal PDF layout for vendor datasheets
- reconstructs explicit parameter/unit/required/offered tables
- reads the offered column without confusing it with requirement/reference columns
- supports two independent numeric parameter/value pairs on one visual row
- supports a final offered value wrapped to the next numeric line
- supports parameter labels continued by an explicit trailing hyphen
- skips ambiguous multi-column rows rather than guessing
Broader deterministic unit conversion
The registry now covers:
- power: W / kW / MW
- voltage: mV / V / kV
- current: mA / A / kA
- frequency: Hz / kHz / MHz
- apparent power: VA / kVA / MVA
- pressure: Pa / kPa / MPa / mbar / bar / psi
- length: mm / cm / m / km / in / ft
- mass: g / kg / t
- force: N / kN
- flow: L/s / L/min / m³/s / m³/h
- temperature: °C / °F / K
Dimension safety remains explicit. Real power is not treated as apparent power, voltage is not current, gauge/absolute pressure suffixes are not collapsed, and frequency is not converted into rotational speed.
Sanitized datasheet regression fixtures
Tests now render vendor-neutral motor, pump and valve layouts into temporary PDFs and verify:
- multi-page source provenance
- revision/metadata noise
- explicit technical tables
- side-by-side fields
- wrapped table continuations
No third-party vendor PDF or confidential project data is embedded in these fixtures.
Batch comparison ergonomics
- multi-vendor Markdown technical bid tabulation export
rank --top Nfor compact terminal display- full JSON / Markdown / HTML / CSV exports remain complete even when terminal output is limited
Safety boundaries
v0.2.1 deliberately does not claim arbitrary merged-cell reconstruction. Coordinate-aligned sparse cells and advanced ambiguous multi-column layouts remain scheduled for v0.2.2 so they can be implemented without positional guessing.
OCR also remains outside the deterministic parser.
Validation
The release branch must pass Ruff and pytest on Python 3.11, 3.12 and 3.13 before merge.
bidlint v0.2.0 — Real-World Engineering Bid Compliance
bidlint v0.2.0
Real-world engineering bid compliance. Evidence before confidence.
bidlint v0.2.0 expands the deterministic compliance core into a more practical technical bid evaluation workflow for engineering specifications, vendor datasheets, bids and submittals.
What's new
- Deterministic engineering unit conversion for:
- Power
- Pressure
- Length
- Flow
- Safer parsing of real-world vendor datasheets
- Support for colon-delimited, two-column and paired-line technical fields
- Conservative engineering terminology normalization
- Project- and vendor-specific aliases with
--aliases - Multi-vendor technical compliance ranking
- Self-contained HTML technical bid tabulation
- Requirement-by-vendor comparison matrix
- CSV audit export for spreadsheet and procurement workflows
- Improved traceability and explicit uncertainty handling
Engineering safety
bidlint only makes a deterministic compliance decision when the available evidence supports it.
Unknown units, missing evidence, ambiguous terminology or qualitative requirements remain:
REVIEW
rather than being converted into an artificial PASS or FAIL.
Evidence before confidence.
Example
Specification: Motor power shall be minimum 10 kW.
Vendor : Motor power: 10000 W
PASS — Offered 10000w (= 10kw) satisfies >= 10kw.