Repository navigation
CI: fail build when audit-harness citation markers leak into compiled output - #1678
marcin-kordas-hoc wants to merge 13 commits into
Conversation
… output Adds a post-build scan step to `.github/workflows/build.yml` that greps `dist/`, `commonjs/`, and `es/` for two internal-only marker patterns: - `\[V[0-9]+\]` — audit-harness citation markers used in spec drafts - `§[[:space:]]*Sources` — section heading used in audit-harness footers Both are conventions from the audit-harness tooling and belong in internal docs/prompts only. If they ever appear in compiled JS it means a comment or string literal slipped through from a spec draft into shipped output — the scan fails the workflow with the offending file path and line number. The step runs after `npm run bundle-all` (which produces the three output directories) and skips gracefully if a directory is missing, so unrelated build failures aren't masked by this guardrail. Manual verification: - Synthesized `dist/foo.js` containing both markers — grep matched both lines and exited 1 with a clear message. - Repeated with clean JS — grep exited 0. - Repeated with no output dirs — step exited 0 (skip path).
✅ Deploy Preview for hyperformula-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for hyperformula-dev-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Performance comparison of head (cd30d48) vs base (d143456) |
Bugbot review #3296952334 flagged that the `if grep ...` form treats grep's exit code 2 (scan/IO error) identically to exit code 1 (no matches) — so a permission or read error on dist/, commonjs/, or es/ would silently green- light the step. Split the rc into 0/1/other and fail the step explicitly on any non-zero, non-1 result.
Validates the build.yml marker-scan step against synthetic fixtures: clean
build, marker in dist/*.js, marker in dist/*.js.map (sourcesContent), marker
in commonjs/*.js, marker in es/*.mjs. Wired as a single self-test step in
build.yml that runs once per OS (node 22, ci install).
Empirically confirmed (probed by planting a marker in src/index.ts and
running `npm run bundle-all`) that source comments survive into:
- commonjs/index.js and es/index.mjs (babel preserves comments)
- dist/hyperformula{,.full}.js (webpack development build preserves comments)
- dist/hyperformula.js.map (`sourcesContent` embeds full original source)
All three surfaces are inside the existing `grep -rn dist commonjs es` scope,
so the scan already covers source-maps. The new self-test pins this behavior
so a future bundler/comment-stripping change cannot silently erode coverage.
Tier-2 hardening: integration test for marker scan + source-map coverageAdded Empirical answer to the SFDIPOT P0 question — do source-maps carry source comments? Yes. Probed by planting
The existing Also added an inline comment block in Verification (local):
New head SHA: |
…test cannot drift The verify step in build.yml previously inlined the audit-marker grep logic while scripts/test-marker-scan.sh kept its own duplicate copy. A workflow-only edit could silently desynchronize the live scan from the self-test fixtures that are supposed to guard it. Move the scan into scripts/marker-scan.sh as a single parameterized entry point (accepts paths as $@, exit 0=clean, 1=dirty, 2+=error). The workflow step now invokes `bash scripts/marker-scan.sh dist commonjs es`, and the self-test drives the SAME script against synthetic fixture roots.
…es output marker-scan grepped only the legacy [V<n>] form, so current markers ([vrf_1], [dec_3], ...) passed the gate; it also scanned only dist/commonjs/es, missing the typings/ and languages/ bundle outputs (both preserve source comments). Extend the grep to the lowercase prefix+_digits grammar, add typings+languages to the CI invocation and the self-test dir list, and add fixtures for both gaps.
… in build-output scan
|
Good flag on the If it ever fires spuriously, two cheap fixes: (1) tighten the pattern to a standalone token / comment-context only ( |
Per review: extend the marker scan to the documentation surfaces. docs/guide (hand-written markdown) was previously unscanned and is a real leak path; it is present in the checkout and now covered. docs/api is generated by a separate docs build, so marker-scan.sh scans it only when present (it skips any missing path).
assert_scan wrote to a hardcoded /tmp/scan-out, bypassing the `trap 'rm -rf "$TMP_ROOT"' EXIT` cleanup and racing on a shared path. Redirect to "$TMP_ROOT/scan-out" so it lives under the per-run mktemp dir and is cleaned up with the rest of the fixtures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 077dcc1. Configure here.
The live CI step (build.yml) scans docs/api and docs/guide, but the self-test's run_marker_scan() mirror loop still omitted them, so the anti-drift adapter had itself drifted and would not catch a docs-path regression. Add both paths to the loop and a docs/guide/*.md fixture case that exercises the surface. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
hyperformula-docs | cd30d48 | Commit Preview URL Branch Preview URL |
Oct 25 2026, 01:59 AM |
…l on missing paths The monorepo move put the engine's build output under hyperformula/, so the check in build.yml scanned paths that no longer exist and passed. docs/api is generated only by docs:build, so build.yml never scanned it. - script/check-citation-markers.mjs replaces scripts/marker-scan.sh and its self-test; `npm run check:citation-markers` is its only caller - one step in build-docs.yml after `npm run docs:build`, which builds both the engine and the docs, instead of a step in each of the 18 build jobs - a missing or empty path fails the check instead of being skipped - the pattern is checked against marker and non-marker samples before each scan - dev-docs/STRUCTURE.md, dev-docs/BUILD.md and script/AGENTS.md list the script Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1678 +/- ##
========================================
Coverage 97.28% 97.28%
========================================
Files 207 207
Lines 16218 16218
Branches 3556 3588 +32
========================================
Hits 15777 15777
Misses 433 433
Partials 8 8 🚀 New features to boost your workflow:
|

Context
The PR adds a CI check that fails when a citation marker from a draft document reaches the build output or the docs.
commonjs,es,typingsanddist, and the API reference indocs/api.script/check-citation-markers.mjs: scans 7 directories:hyperformula/commonjs,dist,es,languages,typings, plusdocs/apianddocs/guide. Exits 1 on a marker and 2 when a directory is missing or empty.package.json:npm run check:citation-markers, the script's only caller..github/workflows/build-docs.yml: one step afternpm run docs:build, which builds both the engine and the docs.dev-docs/BUILD.md,dev-docs/STRUCTURE.md,script/AGENTS.md: list the script and where it runs.build-docs, and a moved output directory fails the check instead of passing it.Before each scan, the script checks its pattern against marker and non-marker samples, so a broken pattern also fails.
How did you test your changes?
After
npm run bundle-allandnpm run typedoc:build-api,npm run check:citation-markersscanned 942 files and exited 0. For each of the 7 directories:In CI, the
build-docsjob ran the check on 943 files and passed.A marker planted in one JSDoc comment in
hyperformula/src, followed by a rebuild, gave 8 hits and exit 1. Also: all 9 marker forms appended to a source map exit 1, with 9 hits. Non-marker look-alikes exit 0. A pattern that matches nothing, or one that matches too much, fails the self-check with exit 2.Compatibility with Excel and Google Sheets
Not applicable.
Public API changes
None.
Out of scope and follow-ups
docs/.vuepress/dist) and thedev-docs/site are not scanned.Types of changes
Related issues
None.
Checklist
dev-docs/pages this change affects – or none needed it.