Skip to content

[GRV-27]: Resolve estimation API and catalog drift#43

Merged
github-actions[bot] merged 1 commit into
mainfrom
symphony/grv-27-resolve-estimation-api-and-catalog-drift
Jun 5, 2026
Merged

[GRV-27]: Resolve estimation API and catalog drift#43
github-actions[bot] merged 1 commit into
mainfrom
symphony/grv-27-resolve-estimation-api-and-catalog-drift

Conversation

@riddim-developer-bot

Copy link
Copy Markdown
Contributor

What & why

llm-cost-estimation re-exported attribution's implemented forecaster but its catalog still described ForecastIssueCost as a planned stub, and it exposed forecastProjectCost / calibrate as throwing not implemented placeholders — even though their implemented analogs already shipped in llm-cost-attribution. This PR makes the docs, README, public exports, and tests agree on what is implemented vs. unsupported, turning the catalog/API alignment check green for estimation.

Resolves GRV-27.

Changes

  • src/index.mjs
    • forecastProjectCost now re-exports attribution's implemented project forecaster — estimation-friendly signature forecastProjectCost(issues, usageSource?, options?) with { size, model } IssuePlans, consistent with forecastIssueCost.
    • Adds calibrateCoverage, re-exported from attribution's implemented coverage backtester.
    • calibrate kept as a deprecated compatibility shim; its error names the supported replacement (calibrateCoverage) instead of not implemented.
  • docs/use-cases.md — rewrites ForecastIssueCost and ForecastProjectCost to describe shipped behavior (no longer "Planned — stub throws"), adds a CalibrateCoverage entry, and documents calibrate as deprecated. ForecastIssueCost now reflects the real (cell, records) shape rather than the never-built CalibrationDataset model.
  • README.md — drops calibrate from the ready-use import example; documents the real forecastProjectCost / calibrateCoverage signatures and the calibrate deprecation.
  • test/smoke.test.mjs — no longer asserts ready APIs throw not implemented: forecastProjectCost forecasts an empty project, calibrateCoverage is asserted exported, and calibrate's error is asserted to name its replacement.

Acceptance criteria

  • docs/use-cases.md accurately describes shipped behavior.
  • ForecastIssueCost no longer described as a planned stub.
  • README import examples do not advertise throwing APIs as ready-to-use.
  • forecastProjectCost delegates to attribution's implemented project forecaster with a documented estimation-friendly signature.
  • calibrate documented as deprecated and omitted from ready-use examples; calibrateCoverage delegates to the implemented calibration/coverage API.
  • Barrel smoke tests no longer assert advertised ready APIs throw not implemented.
  • The one remaining throwing export (calibrate) names its supported replacement.
  • Existing enrichment and CLI forecast behavior preserved (no changes to enrich.mjs, linear-estimate-source.mjs, bin/).
  • Catalog/API alignment turns green for estimation.
  • Estimation package tests pass.

Out of scope (unchanged)

No attribution forecast-math changes, no project-level quota forecasts, no npm publishing / version bumps.

Verification

node --test packages/llm-cost-estimation/test/   # 37 passing, 0 failing
node --check packages/llm-cost-estimation/src/*.mjs  # OK

Re-verified after rebasing onto origin/main (which merged GRV-24's attribution port extraction): the forecastProjectCost / calibrateCoverage re-exports still resolve and all 37 tests pass.

The estimation barrel re-exports attribution's implemented forecaster but
still described ForecastIssueCost as a planned stub and exposed
forecastProjectCost / calibrate as throwing "not implemented" placeholders,
while their implemented analogs already shipped in attribution.

- Re-export forecastProjectCost and calibrateCoverage from
  llm-cost-attribution; both now work with estimation-friendly signatures.
- Keep calibrate as a deprecated shim whose error names calibrateCoverage.
- Rewrite docs/use-cases.md so ForecastIssueCost / ForecastProjectCost /
  CalibrateCoverage describe shipped behavior, not planned stubs.
- Drop calibrate from the README ready-use import example; document the real
  forecastProjectCost / calibrateCoverage signatures and the calibrate
  deprecation.
- Update barrel smoke tests: forecastProjectCost forecasts an empty project,
  calibrateCoverage is exported, calibrate's error names its replacement.
@github-actions github-actions Bot enabled auto-merge (squash) June 5, 2026 07:05
@github-actions github-actions Bot merged commit 347b6dc into main Jun 5, 2026
2 of 3 checks passed
github-actions Bot pushed a commit that referenced this pull request Jun 5, 2026
## Summary

Part of the **llm-cost architecture contracts** Project. Two
deliverables, both scoped to the `llm-cost-attribution` package (per
this issue's title + `llm-cost-attribution` label):

1. **Repair the boundary guard** so its config reflects the package
after the estimation extraction.
2. **Establish the attribution use-case catalog** as the canonical,
complete source of truth for the attribution surface.

### Repair boundary guard —
`packages/llm-cost-attribution/scripts/check-boundary.mjs`

The boundary config carried two **dead references** to modules that were
extracted to `llm-cost-estimation` (in GRV-2 / the estimation split) but
never removed here:

- `src/enrich.mjs` in `coreModules`
- `src/linear-estimate-source.mjs` in `adapterModules`

Neither file exists in this package, so `existsSync` silently skipped
them — the guard *claimed* to protect/classify modules it can no longer
see. Repaired by:

- Removing both dead entries.
- Replacing stale remediation text that still pointed at the moved
`LinearEstimateSource` with port-neutral attribution guidance
(`SessionSource` / `IssueMatcher` / `UsageRecordSource` /
`UsageRecordSink`). The defensive `@linear` / `https` / `fs` /
`child_process` forbidden-package rules are kept.

To repair the *class* of bug (not just the instance),
`test/boundary.test.mjs` now:

- Adds **config-integrity tests** asserting every configured
`coreModules` / `adapterModules` path exists on disk, so dead or phantom
entries fail CI instead of silently passing.
- Exercises the core-imports-adapter rule against a **real** adapter
(`attribution-adapters.mjs`) instead of the removed Linear adapter.

### Establish attribution catalog —
`docs/architecture/use-case-catalog.md`

- Added a canonical intro, the inward dependency rule, and the linkage
to the boundary guard that enforces it.
- Cataloged the two remaining public use cases that were documented in
the package catalog/README but missing here:
**CreateAttributionWorkflow** and **ListKnownIssues**. The catalog now
covers the full attribution public surface.

## Verification

- `npm test` (llm-cost-attribution): **200 pass / 0 fail** (was 198; +2
new config-integrity tests).
- `node scripts/check-boundary.mjs`: **Boundary check passed**.
- `node --check` on changed `scripts/check-boundary.mjs` and
`test/boundary.test.mjs`: ✓.
- Project-acceptance, llm-cost-architecture-contracts — **GRV-26's
portion is fully green**:
  - `architecture-boundary.check.mjs` (runs the repaired guard): ✓
  - `attribution-ports.test.mjs`: ✓
  - catalog/API alignment: **no findings for `llm-cost-attribution`**.
- Rebased onto latest `origin/main` (includes #43 / GRV-27).

## Out of scope (observed, not fixed here)

The non-required project-acceptance gate still reports **one** finding,
in the separate **`llm-cost-estimation`** package, left by the
just-merged GRV-27 (#43):
`packages/llm-cost-estimation/docs/use-cases.md:67` marks the
now-implemented `forecastProjectCost` as planned/stubbed. That is
estimation-catalog territory (GRV-27's rollout), not this attribution
issue — flagged here as a breadcrumb for a follow-up rather than mixing
packages in one PR. `pr-build` (the required gate) excludes the
project-acceptance directory, so this does not block merge.

Co-authored-by: riddim-developer-bot <developer-bot@riddimsoftware.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants