Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
60aed86
lint(scripts): add no-weak-assertions custom check
andrew-bierman May 17, 2026
827f617
docs(plans): add 2026-05-19 coverage ratchet + quality gates plan
andrew-bierman May 20, 2026
af2f382
docs(testing): migrate TESTING.md to docs/testing.md
andrew-bierman May 20, 2026
b4bf4e0
ci(coverage): add ratchet script and baseline file
andrew-bierman May 20, 2026
a72d6d4
chore(package-json): re-sort scripts after Phase 1 additions
andrew-bierman May 20, 2026
d76bd36
ci(coverage): add matrix-driven coverage workflow with ratchet gate
andrew-bierman May 20, 2026
491ebb2
fix(ci): coverage report action path doubling
andrew-bierman May 20, 2026
c4b01d5
docs(etl): pivot remediation plan from Queues+outbox to Workflows
andrew-bierman May 20, 2026
334fbdb
feat(etl): U1 Workflows spike (throwaway POC)
andrew-bierman May 20, 2026
9216908
feat(etl): U1 standalone spike worker — Workflows verified GO
andrew-bierman May 20, 2026
a32f738
feat(etl): U2 schema migration 0048 — Workflows-aware columns
andrew-bierman May 20, 2026
35a45d8
feat(etl): row-boundary-aligned R2 chunker (chunkCsvForR2)
andrew-bierman May 20, 2026
bcc7c9e
feat(etl): CatalogEtlWorkflow — durable ETL via Cloudflare Workflows
andrew-bierman May 20, 2026
eec7ec8
feat(etl): producer cutover — default to Workflow, retain queue fallback
andrew-bierman May 20, 2026
b99bb49
feat(etl): U4 validator hardening — close SSRF, IDN, length, charset …
andrew-bierman May 20, 2026
f92dacd
chore(etl): remove standalone spike worker; wire ETL_WORKFLOW into en…
andrew-bierman May 20, 2026
4af57df
fix(etl): drop `as Error` casts in CatalogEtlWorkflow
andrew-bierman May 20, 2026
fa6ceea
refactor(etl): slim U2 to workflow_instance_id + total_embedding_fail…
andrew-bierman May 20, 2026
1f8432f
feat(etl): U7 invalid_item_logs retention sweep
andrew-bierman May 20, 2026
a1f942c
feat(etl): U6 part 1 — structured logger + error propagation fixes
andrew-bierman May 20, 2026
53bb3a7
feat(etl): U5 (minimal) — workflow-aware retry + reconcile admin endp…
andrew-bierman May 20, 2026
64d1f67
docs(etl): U8 operator runbook for the Workflows pipeline
andrew-bierman May 20, 2026
4bac86e
fix(etl): CI failures — type errors, coverage threshold, hoisted mock
andrew-bierman May 20, 2026
4672fc8
feat(etl): migration 0050 — ETag fail-closed repair + supersession au…
andrew-bierman May 20, 2026
10dbf60
feat(etl): U6 part 2 — @sentry/cloudflare wiring
andrew-bierman May 20, 2026
cbae081
fix(etl): logger uses @packrat/guards type predicates instead of raw …
andrew-bierman May 20, 2026
0f1c057
fix(etl): drop isBoolean import — @packrat/guards doesn't export it
andrew-bierman May 20, 2026
cbab838
feat(etl): GET /api/admin/analytics/catalog/audit endpoint
andrew-bierman May 21, 2026
24423c1
refactor(db): drizzle.config schema path uses in-package re-export
andrew-bierman May 21, 2026
5187b6d
chore(etl): consolidate ETL migrations to single drizzle-kit-generate…
andrew-bierman May 21, 2026
9980ed4
fix: address P0/P1 review findings on ETL workflow
andrew-bierman May 21, 2026
51c77ed
docs: fix plan doc contradiction and stale runbook section
andrew-bierman May 21, 2026
a9e7c3e
🐛 fix: chunk boundary byte offset and retention returning type
andrew-bierman May 21, 2026
086ed13
🐛 fix(etl): address PR review feedback — chunker guards + docs
andrew-bierman May 21, 2026
5b031e1
Merge pull request #2462 from PackRat-AI/fix/etl-pipeline-workflows-m…
andrew-bierman May 21, 2026
8397d9e
fix: strip .csv from workflow instance ID (CF Workflows invalid_id)
andrew-bierman May 21, 2026
0f404b5
🧪 test(api): add unit tests for catalog ETL instanceId construction
andrew-bierman May 21, 2026
9513605
style(api): fix Biome useTemplate lint in instanceId test
andrew-bierman May 21, 2026
d32dff8
🛡️ fix(etl): handle malformed CSV rows gracefully instead of aborting
andrew-bierman May 21, 2026
7b1e6d2
🐛 fix(etl): reduce chunk size 20MB→5MB to prevent WorkflowTimeoutError
andrew-bierman May 21, 2026
f8f7be5
fix(api): clamp KV expirationTtl to minimum 60s (#2466)
mikib0 May 21, 2026
6353df4
🐛 fix(etl): use parser line number in on_skip error log
andrew-bierman May 21, 2026
36f1317
Merge pull request #2465 from PackRat-AI/fix/etl-catalog-sprint-fixes
andrew-bierman May 21, 2026
c64cf9b
✨ feat(etl): add JSONL/NDJSON support to catalog ETL pipeline
andrew-bierman May 21, 2026
603d281
🛠️ fix(json-utils): use @packrat/guards, add unit tests for coverage
andrew-bierman May 21, 2026
916732b
🛠️ fix(etl): replace unsafe casts with @packrat/guards, fix test
andrew-bierman May 21, 2026
2639f80
🛠️ fix(etl): address CR/Copilot comments — chunk skip, imports, types
andrew-bierman May 21, 2026
1b27205
🛠️ fix(json-utils): correct Biome import sort order
andrew-bierman May 21, 2026
4af87df
🛠️ fix(etl): drop explicit err type on on_skip to fix TS overload res…
andrew-bierman May 21, 2026
534e3f6
🛠️ fix(etl): guard err possibly-undefined in on_skip (TS18048)
andrew-bierman May 21, 2026
cd4e13e
🛠️ fix: use pre-computed `message` var in on_skip console.warn
andrew-bierman May 21, 2026
46da63e
🛠️ fix: collapse console.warn to single line for Biome formatter
andrew-bierman May 21, 2026
3af10be
fix(etl): capture csv pump promise to prevent silent hang on R2 errors
andrew-bierman May 21, 2026
3ce56fc
Merge pull request #2471 from PackRat-AI/feat/jsonl-etl-support
andrew-bierman May 21, 2026
58c03c3
fix(api/image-detection): make all schema fields required for OpenAI …
mikib0 May 21, 2026
5049a6f
fix(etl): reduce chunk size 5MB→2MB to clear Marmot WorkflowTimeoutError
andrew-bierman May 21, 2026
06081d7
Merge pull request #2472 from PackRat-AI/fix/image-detection-openai-s…
mikib0 May 21, 2026
d096a4a
fix(etl): address Copilot review — generic comment, doc alignment, ch…
andrew-bierman May 22, 2026
7a63f84
Merge pull request #2473 from PackRat-AI/fix/marmot-chunk-size
andrew-bierman May 22, 2026
13efe08
fix(etl): guard variants.values.join crash when values is a string sc…
andrew-bierman May 22, 2026
fdf16c3
✅ test(etl): cover string-values variant branch in embeddingHelper
andrew-bierman May 22, 2026
1b7cf32
✨ feat(etl): expose failureRate, embeddingFailures, and verification …
andrew-bierman May 22, 2026
ed92701
Merge pull request #2475 from PackRat-AI/fix/etl-variants-join-crash
andrew-bierman May 23, 2026
799a4d0
Merge pull request #2455 from PackRat-AI/chore/ramp-test-coverage
andrew-bierman May 23, 2026
62b65a1
Merge pull request #2476 from PackRat-AI/feat/etl-job-quality-fields
andrew-bierman May 23, 2026
57ac5e5
fix(catalog): allow unknown item weights
andrew-bierman May 23, 2026
2411875
fix(catalog): handle nullable weights in clients
andrew-bierman May 23, 2026
f4b4298
test(api): cover logger forwarding paths
andrew-bierman May 23, 2026
1bcf0ad
test(api): cover json catalog mapping branches
andrew-bierman May 23, 2026
db8f10a
test(api): cover csv catalog mapping branches
andrew-bierman May 23, 2026
889aaa2
test(api): cover timing safe comparison branch
andrew-bierman May 23, 2026
6e6c4a1
Merge pull request #2481 from PackRat-AI/fix-ai-chat-catalog-null-weight
andrew-bierman May 23, 2026
e1f3543
fix(api): guard catalog vector search embeddings
andrew-bierman May 23, 2026
6770217
Merge pull request #2483 from PackRat-AI/codex/hotfix-catalog-vector-…
andrew-bierman May 23, 2026
4540b91
chore: bump version to v2.0.27
mikib0 May 29, 2026
68f2d96
chore: merge main into release/v2.0.27
mikib0 May 29, 2026
c020fee
Potential fix for pull request finding 'CodeQL / Workflow does not co…
mikib0 May 31, 2026
c46e448
Merge pull request #2515 from PackRat-AI/release/v2.0.27
mikib0 May 31, 2026
809c48e
📝 docs(plan): @packrat/utils facade + two-tier guards + layered enfor…
andrew-bierman Jun 1, 2026
4aede82
✨ feat(utils): scaffold @packrat/utils + enroll utility libs
andrew-bierman Jun 1, 2026
c16dbc2
📝 docs(utils): U2 duplication/abstraction sweep findings
andrew-bierman Jun 1, 2026
b973520
✨ feat(utils): curate facade surface + provenance + json utils
andrew-bierman Jun 1, 2026
98c87cc
♻️ refactor(guards): source predicates through @packrat/utils (two-tier)
andrew-bierman Jun 1, 2026
da0fd64
✨ feat(lint): ban reach-around imports of utility libs (noRestrictedI…
andrew-bierman Jun 1, 2026
86b8c19
✨ feat(checks): no-duplicate-utils — flag re-implementations of facad…
andrew-bierman Jun 1, 2026
d57546c
✨ feat(checks): check-utils-provenance — manifest sync + priority enf…
andrew-bierman Jun 1, 2026
d6c4de9
♻️ refactor(lint): port no-raw-typeof + no-raw-regex to ast-grep; add…
andrew-bierman Jun 1, 2026
803c5c6
✨ feat(utils): safeParse strict option + add jscpd/ts-morph devDeps
andrew-bierman Jun 1, 2026
46c8de1
♻️ refactor(utils): rename json helpers safeJson*/stableJson* (avoid …
andrew-bierman Jun 1, 2026
7c70da0
✨ feat(lint): no-primitive-cast — flag `as string/number/boolean`, st…
andrew-bierman Jun 1, 2026
c9ceb14
♻️ refactor: route all JSON through @packrat/utils safeJson* + fix pr…
andrew-bierman Jun 1, 2026
4f7787d
⏪ fix(api): restore logger object-arg API (revert migration scope-creep)
andrew-bierman Jun 1, 2026
d3f9c81
✨ feat(checks): add jscpd + activate all enforcement layers (CI-block…
andrew-bierman Jun 1, 2026
3e524af
🐛 fix(checks): drop `as RankedLib` cast in provenance check (check:ca…
andrew-bierman Jun 1, 2026
cd1bc92
📝 docs(plan): mark utils/guards hardening plan completed
andrew-bierman Jun 1, 2026
7b3f4ab
🔀 Merge origin/development into refactor/utils-guards-hardening
andrew-bierman Jun 1, 2026
f22bc09
🐛 fix(utils): type safeJsonStringify/stableJsonStringify as JSON.stri…
andrew-bierman Jun 1, 2026
75437ab
Merge remote-tracking branch 'origin/development' into refactor/utils…
andrew-bierman Jun 1, 2026
1662d05
🐛 fix(api-client): migrate dev-merged raw typeof to isFunction (no-ra…
andrew-bierman Jun 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ jobs:
run: bun scripts/lint/no-unauth-routes.ts
- name: Check unsafe type casts
run: bun check:casts:strict
- name: Check for duplicate @packrat/utils implementations
run: bun check:utils
- name: Check @packrat/utils provenance manifest
run: bun check:provenance:strict
- name: Check code duplication (jscpd)
run: bun check:duplication
- name: Check types
run: bun check-types
- name: Run Expo Doctor
Expand Down
289 changes: 289 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
name: Coverage

on:
push:
branches: ["main", "development"]
paths:
- "package.json"
- "bun.lock"
- "apps/**"
- "packages/**"
- "scripts/lint/coverage-ratchet.ts"
- "scripts/lint/coverage-baseline-update.ts"
- "scripts/lint/no-weak-assertions.ts"
- "scripts/vitest.config.ts"
- "coverage-baselines.json"
- ".github/workflows/coverage.yml"
pull_request:
branches: ["**"]
paths:
- "package.json"
- "bun.lock"
- "apps/**"
- "packages/**"
- "scripts/lint/coverage-ratchet.ts"
- "scripts/lint/coverage-baseline-update.ts"
- "scripts/lint/no-weak-assertions.ts"
- "scripts/vitest.config.ts"
- "coverage-baselines.json"
- ".github/workflows/coverage.yml"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: write # for baseline auto-commit on main
pull-requests: write # for vitest-coverage-report-action comments

jobs:
# One coverage run per tracked workspace. Uploads the coverage-summary.json
# as an artifact for the ratchet job to aggregate.
coverage:
name: Coverage (${{ matrix.name }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# `summary_path` / `final_path` are repo-relative (used by artifact
# upload + ratchet restore). `summary_relative` / `final_relative`
# are relative to `working_directory` (used by the coverage report
# action, which joins them with working_directory internally).
- name: packages/api
artifact_slug: packages-api
test_command: bun run --cwd packages/api test:unit:coverage
summary_path: packages/api/coverage/unit/coverage-summary.json
final_path: packages/api/coverage/unit/coverage-final.json
summary_relative: ./coverage/unit/coverage-summary.json
final_relative: ./coverage/unit/coverage-final.json
vite_config_path: ./vitest.unit.config.ts
working_directory: ./packages/api
- name: apps/expo
artifact_slug: apps-expo
test_command: bun run --cwd apps/expo test:coverage
summary_path: apps/expo/coverage/unit/coverage-summary.json
final_path: apps/expo/coverage/unit/coverage-final.json
summary_relative: ./coverage/unit/coverage-summary.json
final_relative: ./coverage/unit/coverage-final.json
vite_config_path: ./vitest.config.ts
working_directory: ./apps/expo
- name: packages/mcp
artifact_slug: packages-mcp
test_command: bun run --cwd packages/mcp test --coverage
summary_path: packages/mcp/coverage/coverage-summary.json
final_path: packages/mcp/coverage/coverage-final.json
summary_relative: ./coverage/coverage-summary.json
final_relative: ./coverage/coverage-final.json
vite_config_path: ./vitest.config.ts
working_directory: ./packages/mcp
- name: packages/analytics
artifact_slug: packages-analytics
test_command: bun run --cwd packages/analytics test --coverage
summary_path: packages/analytics/coverage/coverage-summary.json
final_path: packages/analytics/coverage/coverage-final.json
summary_relative: ./coverage/coverage-summary.json
final_relative: ./coverage/coverage-final.json
vite_config_path: ./vitest.config.ts
working_directory: ./packages/analytics
- name: packages/overpass
artifact_slug: packages-overpass
test_command: bun run --cwd packages/overpass test --coverage
summary_path: packages/overpass/coverage/coverage-summary.json
final_path: packages/overpass/coverage/coverage-final.json
summary_relative: ./coverage/coverage-summary.json
final_relative: ./coverage/coverage-final.json
vite_config_path: ./vitest.config.ts
working_directory: ./packages/overpass
- name: packages/units
artifact_slug: packages-units
test_command: bun run --cwd packages/units test --coverage
summary_path: packages/units/coverage/coverage-summary.json
final_path: packages/units/coverage/coverage-final.json
summary_relative: ./coverage/coverage-summary.json
final_relative: ./coverage/coverage-final.json
vite_config_path: ./vitest.config.ts
working_directory: ./packages/units
- name: packages/utils
artifact_slug: packages-utils
test_command: bun run --cwd packages/utils test --coverage
summary_path: packages/utils/coverage/coverage-summary.json
final_path: packages/utils/coverage/coverage-final.json
summary_relative: ./coverage/coverage-summary.json
final_relative: ./coverage/coverage-final.json
vite_config_path: ./vitest.config.ts
working_directory: ./packages/utils
steps:
- uses: actions/checkout@v6

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
env:
PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN: ${{ secrets.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN }}
run: bun install --frozen-lockfile

- name: Run coverage for ${{ matrix.name }}
run: ${{ matrix.test_command }}

- name: Report coverage on PR
if: always() && github.event_name == 'pull_request'
uses: davelosert/vitest-coverage-report-action@v2
with:
name: ${{ matrix.name }}
json-summary-path: ${{ matrix.summary_relative }}
json-final-path: ${{ matrix.final_relative }}
vite-config-path: ${{ matrix.vite_config_path }}
working-directory: ${{ matrix.working_directory }}

- name: Upload coverage summary artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-summary-${{ matrix.artifact_slug }}
path: ${{ matrix.summary_path }}
if-no-files-found: error
retention-days: 7

# Aggregate every workspace's coverage-summary.json and run the ratchet.
# Fails the workflow if any workspace dropped below its baseline.
ratchet:
name: Coverage Ratchet
runs-on: ubuntu-latest
needs: coverage
if: always()
steps:
- uses: actions/checkout@v6

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
env:
PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN: ${{ secrets.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN }}
run: bun install --frozen-lockfile

- name: Download all coverage summaries
uses: actions/download-artifact@v4
with:
pattern: coverage-summary-*
path: artifacts

- name: Restore summaries to their workspace paths
run: |
set -euo pipefail
# Each artifact arrives as artifacts/coverage-summary-<slug>/<path-without-leading-dir>
# actions/download-artifact@v4 unzips a single-file artifact into a directory
# named after the artifact, preserving the source file's basename.
# Copy each back to its expected location so coverage-baselines.json's
# summaryPath entries resolve.
declare -A targets=(
[packages-api]=packages/api/coverage/unit/coverage-summary.json
[apps-expo]=apps/expo/coverage/unit/coverage-summary.json
[packages-mcp]=packages/mcp/coverage/coverage-summary.json
[packages-analytics]=packages/analytics/coverage/coverage-summary.json
[packages-overpass]=packages/overpass/coverage/coverage-summary.json
[packages-units]=packages/units/coverage/coverage-summary.json
)
for slug in "${!targets[@]}"; do
target="${targets[$slug]}"
src_dir="artifacts/coverage-summary-${slug}"
if [ ! -d "$src_dir" ]; then
echo "::warning::missing artifact for $slug — coverage job may have failed"
continue
fi
mkdir -p "$(dirname "$target")"
# Find the single JSON file inside (path may be flat or preserved).
src_file=$(find "$src_dir" -name 'coverage-summary.json' | head -n1)
if [ -z "$src_file" ]; then
echo "::warning::no coverage-summary.json inside artifacts/coverage-summary-${slug}"
continue
fi
cp "$src_file" "$target"
echo "restored $slug → $target"
done

- name: Run coverage ratchet
run: bun check:coverage

# On a green push to main, auto-bump coverage-baselines.json upward.
# Never runs on PRs — PRs cannot edit the baseline file silently.
bump-baseline:
name: Bump Coverage Baselines
runs-on: ubuntu-latest
needs: ratchet
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v6
with:
# Need full token to push the auto-commit back to main.
token: ${{ secrets.GITHUB_TOKEN }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
env:
PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN: ${{ secrets.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN }}
run: bun install --frozen-lockfile

- name: Download all coverage summaries
uses: actions/download-artifact@v4
with:
pattern: coverage-summary-*
path: artifacts

- name: Restore summaries to their workspace paths
run: |
set -euo pipefail
declare -A targets=(
[packages-api]=packages/api/coverage/unit/coverage-summary.json
[apps-expo]=apps/expo/coverage/unit/coverage-summary.json
[packages-mcp]=packages/mcp/coverage/coverage-summary.json
[packages-analytics]=packages/analytics/coverage/coverage-summary.json
[packages-overpass]=packages/overpass/coverage/coverage-summary.json
[packages-units]=packages/units/coverage/coverage-summary.json
)
for slug in "${!targets[@]}"; do
target="${targets[$slug]}"
src_dir="artifacts/coverage-summary-${slug}"
if [ ! -d "$src_dir" ]; then
continue
fi
mkdir -p "$(dirname "$target")"
src_file=$(find "$src_dir" -name 'coverage-summary.json' | head -n1)
if [ -n "$src_file" ]; then
cp "$src_file" "$target"
fi
done

- name: Compute baseline updates
run: bun check:coverage:update

- name: Commit baseline updates
uses: stefanzweifel/git-auto-commit-action@v6
with:
commit_message: "chore(coverage): bump baselines after green main"
file_pattern: coverage-baselines.json

# The scripts test suite — verifies the ratchet and assertion-lint analyzers
# themselves on every PR that touches them or their tests.
scripts-tests:
name: Scripts Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
env:
PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN: ${{ secrets.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN }}
run: bun install --frozen-lockfile
- name: Run scripts test suite
run: bun test:scripts
3 changes: 3 additions & 0 deletions .github/workflows/eas-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ on:
required: false
type: string

permissions:
contents: read

jobs:
update:
name: Publish EAS Update
Expand Down
Loading
Loading