Skip to content

feat(bid-leveling): level bids on bid day with an interactive tab and Excel export - #6

Merged
mikeastock merged 2 commits into
mainfrom
bid-leveling-v3
Oct 5, 2026
Merged

mikeastock merged 2 commits into
mainfrom
bid-leveling-v3

Conversation

@mikeastock-bot

@mikeastock-bot mikeastock-bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Rebuilds bid-leveling around bid day: an estimator levels one trade package under deadline and needs the leveled tab, the open gaps, and the questions to send each bidder.

  • In: the bids as received (PDF proposals, bid-form spreadsheets, email quotes, one-line lump sums) plus the scope sheet when there is one
  • Out:
    • one self-contained interactive HTML bid tab
    • an Excel workbook with formula-backed totals
    • a Markdown brief with the questions for each bidder
  • No award recommendation; nothing is sent to a bidder
Preview (Leveled totals)
Preview
Preview (Gaps and plugs)
Preview
Preview (Scope matrix)
Preview
flowchart LR
  A[bids + scope sheet] -->|agent extracts,<br>cites every quote| B[bid-data.json]
  B --> C[level.mjs]
  C --> D[bid-brief.md]
  C --> E[bid-tab.html]
  C --> X[bid-tab.xlsx]
  E -->|accept or enter plugs,<br>alternates, tax and bond| E
  E -->|Export to Excel| X
  E -->|export / import| F[scenario.json]
  F -->|--scenario| C
Loading

How it works

  • scripts/leveling-core.mjs is a pure module with no dependencies. level.mjs inlines it into the HTML, so the browser recomputes with the same code. The page is pre-rendered and reads correctly with scripts blocked.
  • Leveled total = base + plugs + adjustments + accepted alternates + carried basis items.
  • Suggested plugs: for an excluded or unmentioned base row, the script suggests the highest itemized price another bidder gave for the same row and names its source. A suggestion doesn't count until the estimator accepts it. Unclear scope gets no suggestion; the bidder gets a question instead.
  • A bid is complete only when:
    • every base gap has a plug
    • every accepted alternate is priced
    • every carried tax or bond item has a figure
  • Only complete bids compete for "lowest complete".
  • Flags:
    • itemized lines that don't add up to the total
    • addenda not acknowledged
    • scope from another package carried in a bid, with a suggested removal
    • alternates nobody asked for
    • tax or bond not on a common basis
  • Excel: the XLSX is written by the same module, from the browser or with --xlsx. Plugs and adjustments are SUMIFS over their sheets, so the workbook recomputes when edited.
  • Fixes the 2.0.0 review's P1: every bid must record every package row, and plugs are rejected anywhere but a gap on a base row. A sloppy extraction can no longer be turned into a "complete" low number.
node scripts/level.mjs bid-data.json bid-tab.html --brief bid-brief.md --xlsx bid-tab.xlsx
node scripts/level.mjs bid-data.json --json --scenario exported-scenario.json

Sample

Cedar Hollow clinic, package 09A drywall. The four bids ship as the files an estimator actually gets, in samples/bids/:

  • a two-page PDF proposal
  • a bid-form XLSX with its cover email
  • an email quote
  • a one-line lump sum, revised the morning after bids closed

Planted problems:

  • Summit cites Addendum 1 only and misses the Addendum 2 lobby finish
  • Prairie's bid form adds up to $872,700 against a stated $871,200
  • Prairie carries $46,000 of ACT ceilings that belong to package 09B
  • Summit offers a lift deduct nobody asked for
  • bond and tax are on four different bases

With the estimator's first pass (estimator-scenario.json), Prairie is the lowest complete bid at $833,700. Ridgeline has the lowest base bid ($789,500) but stays incomplete with eight open items.

Removed

level_bids.py and its three references, the 2.0.0 samples, the Millbrook roofing task (it graded the 2.0.0 Markdown contract), and the 2.0.0 review harness, which depended on an unversioned /tmp checkout. The version is now 3.0.0 and the marketplace version 0.6.0. .eml is now inlined in the catalog.

Verification

  • evals/tasks/bid-leveling/leveling-core.test.mjs: 18 tests, now in CI. They include byte-for-byte comparison of the bundled HTML, brief and XLSX against a fresh build, plus escaping of bid text in the HTML.
  • Nine deliberate breaks to the core each failed between 1 and 7 tests.
  • XLSX in LibreOffice:
    • the values match the tab
    • with cached values stripped and one plug switched off, Northgate recomputed from $893,500 to $852,300
  • Chromium:
    • accept a suggestion
    • enter a plug, and reject an invalid amount
    • toggle the alternate and carry the bond
    • export to Excel, export the scenario, reset, then import it
    • 390px width
    • the static view with scripts removed
    • axe: 0 violations
  • Not yet tested: a fresh agent extracting bids it hasn't seen. The arithmetic is tested; judgment calls such as "not mentioned" versus "unclear" aren't.

Note

Rework bid-leveling skill to an interactive bid-day tab with Excel export

  • Replaces the Markdown comparison-template workflow with a full bid-day leveling pipeline: a JSON data contract, extraction guidance, and a Node CLI in level.mjs that validates bid data, runs the analysis, and assembles outputs.
  • Adds a dependency-free core in leveling-core.mjs that computes per-bid leveled totals, completeness, gaps, flags, questions, and suggested plugs, and renders the interactive tab, brief, and workbook.
  • The interactive tab (via app.js) supports accepting/clearing plugs with sources, entering basis and adjustment amounts, toggling alternates, and importing a validated bid-tab JSON scenario in the browser.
  • Adds a bundled sample package (scope sheet, four bidder emails/files, scenario, and checked-in HTML/XLSX/brief outputs) plus a Node test suite that runs in CI and checks output reproducibility.
  • Behavioral Change: skill version bumps 2.0.0 → 3.0.0 and marketplace package 0.5.0 → 0.6.0; the old Markdown comparison template and inline estimator-decisions sample format are removed, and catalog consumers see the new summary and manifest.

Macroscope summarized 44d1054.

… Excel export

Replace the Python Markdown comparison with a dependency-free JS core shared
by the CLI and a self-contained HTML tab. Gaps get sourced plug suggestions
that never count until accepted; tax and bond can be carried on a common
basis; alternates toggle into totals; the tab exports a formula-backed XLSX
and a re-importable scenario. New realistic four-bid drywall sample.
@macroscopeapp

macroscopeapp Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting).

This review would cost an estimated $8.15, which exceeds your per-review limit of $3.00.

The top 3 files driving up this estimate:

File Diff Size Estimate
skills/bid-leveling/scripts/leveling-core.mjs 56.57KB $2.83
skills/bid-leveling/samples/bid-data.json 21.06KB $1.05
evals/reviews/bid-leveling/REPORT.md 16.30KB $0.81

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude the file(s) above from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

@mikeastock
mikeastock merged commit 8e199cf into main Oct 5, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants