🦄 new(pipeline): entry body model (§6.0) - #36
Conversation
Resolves the data-architecture spec's 6.0 prerequisite: ideal-form-
first schema (maintainer directive) with prose collapse + typed
grammar index, senses as {label, gloss, units[]} trees, stems for
binyan sections. Drops refs (98.1k items measured 99.97% derivable
from inline citations) and quotes (vestigial Sefaria importer
artifact, unused even by Sefaria). Import mapping with per-region
confidence + fallbacks, census/fixture plan (72 broken sense
sequences, ibid classes, orphan refs), byte round-trip gates.
Also ignores .superpowers/ (brainstorm scratch) and Word lock files.
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Maintainer review round 1: merge <ref rid>/<cite ref> into one <cite ref> tag (value is rid or canonical Sefaria ref; validator and app router dispatch on the unambiguous rid pattern); record the dual-destination routing requirement (internal primary link + Sefaria arrow icon, both derived per D7); commit to a formal JSON Schema as the documented generic spec (B11). Signed-off-by: Brian L. <brian@uniquepixels.xyz>
13-task plan for the 6.0 prerequisites: source reader, citation detector, corpus census, fixture corpus, five TDD parse rules with byte round-trip gates, formal JSON Schema (validator dep deferred to maintainer per CP-2a), read-only full-corpus dry-run, maintainer eyes-on review gate, and parent-spec amendment PR. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Rename mislabeled linesOf test (it asserts blanks are yielded, not skipped) and document the linesOf export in the module README — both from Task 1 quality re-review. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Add hadLeadingSlash and malformed to CitationHit. When an anchor's href quote is never closed, findCitations now flags it instead of silently swallowing the following valid anchor and cross-attributing its data-ref (D00478, J00597). Also short-circuits when a string has no closing </a> at all. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
findNextBoundary's nested-open-tag path silently dropped the outer anchor whenever a valid open tag's own </a> was missing and a following refLink open tag was found first. Corpus-wide this fired 474 times: 471 are the benign Sefaria nested- duplicate quirk (outer/inner share an identical href), but 3 were genuine citation losses with no hit and no flag at all (D00478, J00597, J00603). Now every such open tag is emitted as a malformed hit whose span covers just the open tag, then scanning resumes from the nested tag as before. Consumers can mechanically tell the two classes apart: adjacent hits with an identical href are the benign duplicate quirk. Also softened the stale O(N²)-on-blobs doc-comment: measured linear in practice after the earlier rewrite. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Mirror grammar.ts's parseMarker convention: quarantine now
returns {unknown: raw} instead of bare null, so the raw
sense.number token survives for reporting. Narrows the letter
class from [A-Za-z] to [a-z] (corpus has zero letter labels;
lettered.ts's synthesized sub-item labels are lowercase-only).
Updates README.md's module table — the listed modules are all
implemented now, only dry-run.ts/review.ts remain planned.
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Task 11 review follow-up: prove evaluateRoundTrip actually catches corruption instead of only passing clean fixtures, and note why trace.problems goes unused on the run path. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
PR #34 widened the biome pipeline override to subdirectories and sanctioned snake_case type properties, making the per-field suppressions in types.ts unused (warning-level under qa:lint). Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Repair passes landed in 43e2afc; gates green, three rows deferred to eyes-on (D00470, K00081, R00519) per the report. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Parent-spec amendments landed as PR #35 (doc/body-model-amendments, docs-only to main): four edit groups, changelog row, forward links resolving on spec-branch merge. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Census has long met its acceptance (report sections, unit-tested classifiers, docs/v2/body-census.md with measured numbers; verify command re-run clean 2026-08-05); status was stale in_progress. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
CP-1 passed 2026-07-10 and is recorded verbatim on main (2026-07-03-v2-overhaul-design.md §7, PR #33). All acceptance criteria re-verified: changelog row present via 'git show origin/main:...' grep, evidence and restart answer recorded, Phase 2 proceeded. Status was stale pending. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Pre-PR local CodeRabbit review of the full branch diff (base v2), 25 findings triaged, each verified against code before acting: - dry-run-report: FIXTURE_SAMPLE_RIDS catches up with Task 15's four lettered fixture rids (schema sample 129→133; surfaces a 4th empty-binyan-form failure, same known Finding 3 root cause) - repairs: cite-escape no longer materializes definition:"" onto grammar-only senses; write-back only on change - grammar: own-key VOCAB lookup (inherited members can't match) - review: explicit guard for docs[name] fixes pre-existing tsc error under noUncheckedIndexedAccess - lint gate: hoist per-call regexes, reasoned noDelete suppression (bun qa now fully green: format, lint -w, 212 tests, tsc) - form-sections test: no-collateral sweep now includes label-quarantines + numbering-extras classes - body-dryrun doc: Finding 6 table was stale (pre-Task-15) vs the current headline; both now match the regenerated report; Finding 3/7 renumbered totals re-anchored - fixtures README: add missing plural/form-sections rows; note A00043's slash-less href; stale plural.ts comment refs updated - design doc: status Draft → Reviewed (2026-08-05 §6.0 review) Skipped (with reasons, see PR notes): cite.ts trailing-unclosed- anchor change (deliberate pinned fast-path, zero corpus incidence measured); maintainer-authored review-doc content edits; task 9 status revert (evidence recorded in prior commit). Signed-off-by: Brian L. <brian@uniquepixels.xyz>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
jastrow | fb08458 | Aug 06 2026, 02:51 PM |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
📝 WalkthroughWalkthroughThis PR adds the Entry Body Model pipeline. It includes source readers, parsers, census tools, deterministic fixtures, schema validation, dry-run verification, migration repairs, maintainer review documents, reports, and CLI scripts. ChangesEntry Body Model pipeline
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Resolves the three CodeQL high alerts on PR #36: - stripTags (census.ts, review.ts): strip to a fixed point so fragments re-composed by one pass can't survive (js/incomplete-multi-character-sanitization). Corpus-verified byte-identical to the single-pass version over all 32,512 entries (0 differing strings), so no census/report drift. - FORM_SECTION_PATTERNS (census.ts): escape every regex special, not just dots (js/incomplete-sanitization). No-op for the closed marker vocabulary; future markers safe by construction. bun qa green; body:census and body:dry-run outputs unchanged. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
The one numbering-gap row of 39 absent from every repairs.ts bucket (found via PR #36 review). Source verified: senses 1,2,4 with '—3) to save' in-text at the end of sense 2 — the same swallowed-marker shape as Q00547. Listed as no-byte-change for this PR's bookkeeping; the maintainer has since ruled the whole swallowed-marker class must be structurally split — that lands as its own fixtured rule (follow-up task), which will supersede CONFIRMED_NO_CHANGE. Signed-off-by: Brian L. <brian@uniquepixels.xyz>
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 27
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@admin/pipeline/body/census.ts`:
- Around line 86-89: Update the JSDoc comment describing the phantom-sense
check, replacing the `*is*` emphasis markers with backticks or plain wording so
it no longer triggers useSingleJsDocAsterisk; preserve the surrounding
explanation.
- Line 63: Update the SENSE_NUMBER regular expression to use a named capture
group, then adjust its consumers to read the captured value through the match
result’s groups property. Preserve the existing numeric extraction behavior and
follow the named-group pattern used elsewhere in census.ts and labels.ts.
- Around line 444-506: Reduce cognitive complexity in censusEntry by extracting
the walkSenses per-sense processing—including definition counting, lettered and
plural detection, form-marker collection, and citation/boundary/ibid
tallying—into a helper. Have the helper return the per-entry flags and collected
form markers, then leave censusEntry responsible only for applying those results
to the accumulator and retaining the existing sequence and opener handling.
In `@admin/pipeline/body/cite.ts`:
- Around line 89-92: Update findCitations in admin/pipeline/body/cite.ts at
lines 89-92 to gate the fast path on the presence of class="refLink" rather than
</a>, so open tags are scanned without closing tags; at lines 114-118, push the
current hit with malformed: true before breaking when no closing content follows
the open tag, matching the nested-open handling.
In `@admin/pipeline/body/dry-run-verify.ts`:
- Line 166: Update the condition in the dry-run verification logic to use an
explicit length comparison for sibling.units, replacing the implicit non-empty
check while preserving the existing gloss comparison.
In `@admin/pipeline/body/dry-run.test.ts`:
- Around line 179-215: The test file exceeds the per-file line budget and the
round-trip sweep is too complex; split the four `evaluateRoundTrip` canary
suites out of the current `buildBody round-trip` block into a separate
`dry-run-verify.test.ts`. In the remaining test, update the loop that builds
`mismatches` around `loadFixture`, `buildTrace`, and `evaluateRoundTrip` to use
a small table-driven list of the four gate checks (`rejoin`, `units`,
`lettered`, `formSection`) so the per-entry validation stays the same while
lowering cognitive complexity.
In `@admin/pipeline/body/dry-run.ts`:
- Around line 188-197: Update buildStem to stop defaulting grammar.verbal_stem
to an empty string. Enforce a loud failure or record the missing verbal_stem for
quarantine at composition time, following the existing policy in repairs.ts, and
ensure no schema-invalid BodyStem is emitted.
In `@admin/pipeline/body/fixtures/extract.ts`:
- Around line 15-232: Resolve the noExcessiveLinesPerFile diagnostic for the RID
catalog in CLASSES while keeping the catalog reviewable: either move the
reviewed catalog data into an appropriate separate data file and preserve its
existing structure, or add a narrowly scoped Biome suppression around this
catalog with a clear reason. Do not alter the RID memberships or categories.
In `@admin/pipeline/body/grammar.test.ts`:
- Around line 56-58: Update the parseMarker census coverage setup around
describe.skipIf to avoid relying on an unpinned Bun-specific API: either pin the
repository’s Bun runtime to a compatible version or replace describe.skipIf with
a supported equivalent such as it.skipIf or a conditional guard, while
preserving the test’s behavior when REPORT_PATH is absent.
In `@admin/pipeline/body/labels.test.ts`:
- Around line 133-141: Update the corpus sweep test around readSourceEntries and
tallyLabels to tally entries inside the for-await loop instead of collecting
them in an entries array. Preserve the existing distinct-label assertions and
keep tallyLabels involved, adapting its input only if needed to support
streaming.
In `@admin/pipeline/body/lettered.test.ts`:
- Around line 10-11: Update the docstring describing the fixture set near the
test fixture declaration to state that it contains 9 entries instead of 5,
keeping it consistent with the split definitions and the assertion in the test.
In `@admin/pipeline/body/migrate-dry.ts`:
- Around line 164-195: Contain failures from applyRepairs within processEntry by
catching the per-entry error, recording the failure in the report, and allowing
the corpus walk to continue; preserve the loud-failure policy by rethrowing
after the walk completes. Update printSummary to include the recorded failure
count, using the report’s existing failure-tracking structure consistently.
In `@admin/pipeline/body/repairs.test.ts`:
- Around line 7-23: Update the FIXTURES paths used by loadFixtures to resolve
relative to the test file via import.meta.dir, matching dry-run.test.ts.
Preserve the existing fixture filenames and readSourceEntries iteration while
removing the dependency on the process working directory.
In `@admin/pipeline/body/repairs.ts`:
- Around line 293-300: Remove the duplicate recursive walkSensesDeep generator
from admin/pipeline/body/repairs.ts#L293-L300 and
admin/pipeline/body/migrate-dry.ts#L60-L67, then import and reuse the shared
source-sense walker exported by census.ts in both modules. Keep existing callers
unchanged and retain only one implementation.
- Around line 14-19: Replace the inline TODO in the repairs documentation with a
concrete tracking reference for the pending notes mechanism, linking the
design-doc changelog and required entry.schema.json update. Preserve the
existing explanation that deviations remain in the record and migration report
until notes support is implemented.
In `@admin/pipeline/body/source.ts`:
- Around line 20-34: Update the linesOf async generator to flush the TextDecoder
after the chunk loop by calling decoder.decode() without stream mode and
appending the result to tail before splitting or yielding the final content.
Preserve the existing line handling while ensuring incomplete trailing UTF-8
sequences surface as decoding errors.
In `@docs/superpowers/plans/2026-07-11-entry-body-model.md.tasks.json`:
- Line 151: Update the lastUpdated field in the task record to the actual final
modification timestamp reflecting completion of Tasks 15–17 on August 5, 2026,
replacing the stale July 15, 2026 value.
In `@docs/v2/body-census.md`:
- Around line 173-178: Correct the Finding 8 coverage statement to match the
`lettered` selection in `extract.ts`: either list all 189 RIDs as fixtures or
explicitly describe the fixtures as a reviewed sample, rather than claiming
exhaustive coverage.
In `@docs/v2/body-dryrun.md`:
- Around line 178-179: Update the reported non-zero evidentiary citation share
in the body dry-run statistics from 60.7% to 60.8%, while leaving the
accompanying counts and surrounding text unchanged.
In `@docs/v2/body-migration.md`:
- Line 28: Update the schema validation baseline in the “Schema validation”
table of body-migration.md to report 4 in-sample failures, matching the current
body-dryrun.md results; alternatively, explicitly label 3 as a dated historical
baseline.
In `@docs/v2/body-review/01-broken-sequences.md`:
- Around line 25-29: Complete the maintainer-review evidence in
docs/v2/body-review/01-broken-sequences.md lines 25-29 by filling every blank
Decision cell or adding an unambiguous section-level decision covering all
listed rows. Update docs/v2/body-review/00-INDEX.md lines 21-27 to replace
“awaiting review” with the recorded completed status for each reviewed document.
In `@docs/v2/body-review/02-orphan-refs.md`:
- Line 68: Correct the closing note by changing “where” to “were,” “concered” to
“concerned,” and “Jastow” to “Jastrow,” then ensure the file ends with exactly
one newline.
In `@docs/v2/body-review/03-quotes-stragglers.md`:
- Line 23: Update the provenance note to use “Sefaria developers” instead of
“Sefaria Devs” and correct the typo “supprised” to “surprised,” preserving the
rest of the note.
In `@docs/v2/body-review/04-label-quarantines.md`:
- Line 16: Correct the typo in the D00341 decision note by changing “begining”
to “beginning,” without altering the surrounding notation or content.
In `@docs/v2/sefaria-report.md`:
- Around line 292-303: Add the text language identifier to both fenced code
blocks in the documented examples, including the block showing the current
structure and the block showing the faithful structure, while leaving their
contents unchanged.
- Around line 156-167: The duplicated nested-anchor metric must use an explicit
scope consistently: in docs/v2/sefaria-report.md lines 156-167, either label 475
as definition anchors only or change it to the all-field total of 1,230; in
docs/v2/upstream-issues.md line 21, retain 1,230 only if the all-field scope,
including 475 definition and 755 language_reference anchors, is stated.
In `@docs/v2/upstream-issues.md`:
- Line 16: Update the issue row for P00855, P00856, and P00860 to list the
served headwords עָמַך I, עָמַך II, and עֶמַך separately from their corrected
print headwords עָמַד I, עָמַד II, and עֶמֶד, preserving the existing issue
references and status.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2a211f40-4873-4d6c-92a7-0b38ce8f6aed
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (65)
.gitignoreadmin/pipeline/body/README.mdadmin/pipeline/body/census.test.tsadmin/pipeline/body/census.tsadmin/pipeline/body/cite.test.tsadmin/pipeline/body/cite.tsadmin/pipeline/body/dry-run-report.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/dry-run.tsadmin/pipeline/body/fixtures/README.mdadmin/pipeline/body/fixtures/baseline.jsonladmin/pipeline/body/fixtures/broken-sequences.jsonladmin/pipeline/body/fixtures/extract.tsadmin/pipeline/body/fixtures/form-sections.jsonladmin/pipeline/body/fixtures/label-quarantines.jsonladmin/pipeline/body/fixtures/lettered.jsonladmin/pipeline/body/fixtures/numbering-extras.jsonladmin/pipeline/body/fixtures/origin-splits.jsonladmin/pipeline/body/fixtures/orphans.jsonladmin/pipeline/body/fixtures/plural.jsonladmin/pipeline/body/fixtures/quotes-stragglers.jsonladmin/pipeline/body/fixtures/stems.jsonladmin/pipeline/body/fixtures/units-hard.jsonladmin/pipeline/body/form-sections.test.tsadmin/pipeline/body/form-sections.tsadmin/pipeline/body/grammar.test.tsadmin/pipeline/body/grammar.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/labels.tsadmin/pipeline/body/lettered.test.tsadmin/pipeline/body/lettered.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/rejoin.test.tsadmin/pipeline/body/rejoin.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/repairs.tsadmin/pipeline/body/review.test.tsadmin/pipeline/body/review.tsadmin/pipeline/body/source.test.tsadmin/pipeline/body/source.tsadmin/pipeline/body/types.tsadmin/pipeline/body/units.test.tsadmin/pipeline/body/units.tsadmin/pipeline/schema/entry.schema.jsonadmin/pipeline/schema/entry.schema.test.tsbiome.jsondocs/specs/2026-07-11-entry-body-model-design.mddocs/superpowers/plans/2026-07-03-v2-phase0-1.md.tasks.jsondocs/superpowers/plans/2026-07-11-entry-body-model.mddocs/superpowers/plans/2026-07-11-entry-body-model.md.tasks.jsondocs/v2/body-census.mddocs/v2/body-dryrun.mddocs/v2/body-migration.mddocs/v2/body-review/00-INDEX.mddocs/v2/body-review/01-broken-sequences.mddocs/v2/body-review/02-orphan-refs.mddocs/v2/body-review/03-quotes-stragglers.mddocs/v2/body-review/04-label-quarantines.mddocs/v2/body-review/05-unit-segmentation-sample.mddocs/v2/body-review/06-empty-binyan-forms.mddocs/v2/body-review/07-italic-lettered-markers.mddocs/v2/sefaria-report.mddocs/v2/upstream-issues.mdpackage.json
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Workers Builds: jastrow
⚠️ CI failures not shown inline (1)
GitHub Check: Workers Builds: jastrow: Workers Builds: jastrow
Conclusion: failure
Build ID: [710d9e31-4017-43fe-8310-f32514330f91](https://dash.cloudflare.com/cf68e0017c53376defadebeecd91fda2/workers/services/view/jastrow/production/builds/710d9e31-4017-43fe-8310-f32514330f91)
Script: [jastrow](https://dash.cloudflare.com/cf68e0017c53376defadebeecd91fda2/workers/services/view/jastrow/production)
🧰 Additional context used
📓 Path-based instructions (2)
**
⚙️ CodeRabbit configuration file
**: General project rules:
- This is a vanilla JS static site PWA. No bundler, no framework, no npm packages at runtime.
- All JS runs in the browser unless under
admin/(maintainer tooling, which uses Bun).- Repo layout (v2):
app/public app,admin/tooling (incl.admin/pipeline/),data/data only.- Biome enforces lint and formatting.
- DOMPurify is loaded via CDN with SRI for XSS sanitization.
Files:
docs/superpowers/plans/2026-07-03-v2-phase0-1.md.tasks.jsonadmin/pipeline/body/fixtures/stems.jsonladmin/pipeline/body/review.test.tsadmin/pipeline/body/fixtures/baseline.jsonladmin/pipeline/body/fixtures/numbering-extras.jsonladmin/pipeline/body/fixtures/README.mdadmin/pipeline/body/fixtures/orphans.jsonladmin/pipeline/body/fixtures/label-quarantines.jsonlbiome.jsonadmin/pipeline/body/fixtures/lettered.jsonladmin/pipeline/body/fixtures/form-sections.jsonladmin/pipeline/body/rejoin.test.tsdocs/v2/upstream-issues.mdadmin/pipeline/body/grammar.test.tsdocs/v2/body-review/01-broken-sequences.mdadmin/pipeline/body/types.tsdocs/v2/body-dryrun.mddocs/v2/body-review/02-orphan-refs.mdadmin/pipeline/body/rejoin.tsadmin/pipeline/body/fixtures/origin-splits.jsonlpackage.jsonadmin/pipeline/body/fixtures/quotes-stragglers.jsonladmin/pipeline/body/lettered.test.tsdocs/v2/body-review/00-INDEX.mdadmin/pipeline/body/fixtures/units-hard.jsonldocs/v2/body-review/07-italic-lettered-markers.mddocs/v2/body-review/04-label-quarantines.mdadmin/pipeline/body/README.mdadmin/pipeline/body/cite.test.tsadmin/pipeline/body/fixtures/broken-sequences.jsonldocs/v2/body-review/03-quotes-stragglers.mdadmin/pipeline/body/units.tsadmin/pipeline/body/form-sections.test.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/census.test.tsadmin/pipeline/body/source.tsdocs/v2/body-review/06-empty-binyan-forms.mdadmin/pipeline/body/fixtures/plural.jsonldocs/v2/body-review/05-unit-segmentation-sample.mddocs/v2/body-census.mdadmin/pipeline/body/lettered.tsadmin/pipeline/body/fixtures/extract.tsadmin/pipeline/body/labels.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/source.test.tsadmin/pipeline/schema/entry.schema.jsonadmin/pipeline/body/grammar.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/units.test.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/schema/entry.schema.test.tsadmin/pipeline/body/cite.tsdocs/superpowers/plans/2026-07-11-entry-body-model.md.tasks.jsonadmin/pipeline/body/census.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/form-sections.tsdocs/v2/body-migration.mdadmin/pipeline/body/dry-run-report.tsadmin/pipeline/body/review.tsadmin/pipeline/body/dry-run.tsdocs/specs/2026-07-11-entry-body-model-design.mddocs/v2/sefaria-report.mdadmin/pipeline/body/repairs.tsdocs/superpowers/plans/2026-07-11-entry-body-model.md
admin/**
⚙️ CodeRabbit configuration file
admin/**: Maintainer tooling that runs on Bun (not deployed). Includes:
admin/pipeline/— data pipeline from the Sefaria source (fetch, transform, validate, emit)- Admin tool v2 (Phase 3) will live here too
consoleand sequential awaits over streams are expected here
Files:
admin/pipeline/body/fixtures/stems.jsonladmin/pipeline/body/review.test.tsadmin/pipeline/body/fixtures/baseline.jsonladmin/pipeline/body/fixtures/numbering-extras.jsonladmin/pipeline/body/fixtures/README.mdadmin/pipeline/body/fixtures/orphans.jsonladmin/pipeline/body/fixtures/label-quarantines.jsonladmin/pipeline/body/fixtures/lettered.jsonladmin/pipeline/body/fixtures/form-sections.jsonladmin/pipeline/body/rejoin.test.tsadmin/pipeline/body/grammar.test.tsadmin/pipeline/body/types.tsadmin/pipeline/body/rejoin.tsadmin/pipeline/body/fixtures/origin-splits.jsonladmin/pipeline/body/fixtures/quotes-stragglers.jsonladmin/pipeline/body/lettered.test.tsadmin/pipeline/body/fixtures/units-hard.jsonladmin/pipeline/body/README.mdadmin/pipeline/body/cite.test.tsadmin/pipeline/body/fixtures/broken-sequences.jsonladmin/pipeline/body/units.tsadmin/pipeline/body/form-sections.test.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/census.test.tsadmin/pipeline/body/source.tsadmin/pipeline/body/fixtures/plural.jsonladmin/pipeline/body/lettered.tsadmin/pipeline/body/fixtures/extract.tsadmin/pipeline/body/labels.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/source.test.tsadmin/pipeline/schema/entry.schema.jsonadmin/pipeline/body/grammar.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/units.test.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/schema/entry.schema.test.tsadmin/pipeline/body/cite.tsadmin/pipeline/body/census.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/form-sections.tsadmin/pipeline/body/dry-run-report.tsadmin/pipeline/body/review.tsadmin/pipeline/body/dry-run.tsadmin/pipeline/body/repairs.ts
🧠 Learnings (1)
📚 Learning: 2026-07-05T16:14:54.518Z
Learnt from: UniquePixels
Repo: UniquePixels/jastrow PR: 25
File: admin/pipeline/fetch.ts:48-75
Timestamp: 2026-07-05T16:14:54.518Z
Learning: For maintainer-run pipeline scripts under admin/pipeline (including admin/pipeline/fetch.ts), avoid adding or recommending a whole-transfer AbortSignal.timeout() for large downloads (e.g., multi-GB dumps). A fixed end-to-end timeout can abort valid successful runs. If cancellation/robustness is needed, prefer an inter-chunk idle timeout (no progress for N seconds) with appropriate retry behavior rather than timing out the entire transfer. Until the admin tool provides UI-driven cancellation/progress, the accepted recovery path for manual reruns is ctrl-C and rerunning the script.
Applied to files:
admin/pipeline/body/review.test.tsadmin/pipeline/body/rejoin.test.tsadmin/pipeline/body/grammar.test.tsadmin/pipeline/body/types.tsadmin/pipeline/body/rejoin.tsadmin/pipeline/body/lettered.test.tsadmin/pipeline/body/cite.test.tsadmin/pipeline/body/units.tsadmin/pipeline/body/form-sections.test.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/census.test.tsadmin/pipeline/body/source.tsadmin/pipeline/body/lettered.tsadmin/pipeline/body/fixtures/extract.tsadmin/pipeline/body/labels.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/source.test.tsadmin/pipeline/body/grammar.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/units.test.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/schema/entry.schema.test.tsadmin/pipeline/body/cite.tsadmin/pipeline/body/census.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/form-sections.tsadmin/pipeline/body/dry-run-report.tsadmin/pipeline/body/review.tsadmin/pipeline/body/dry-run.tsadmin/pipeline/body/repairs.ts
🪛 ast-grep (0.45.0)
admin/pipeline/body/census.ts
[warning] 237-243: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(
// Escape every regex special (not just .) even though MARKERS
// is a closed literal vocabulary — CodeQL js/incomplete-
// sanitization, and future markers stay safe by construction.
${marker.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')}.{0,120}?(?<![(\\w])1\\)\\s,
'su',
)
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
[warning] 237-243: Do not use variable for regular expressions
Context: new RegExp(
// Escape every regex special (not just .) even though MARKERS
// is a closed literal vocabulary — CodeQL js/incomplete-
// sanitization, and future markers stay safe by construction.
${marker.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')}.{0,120}?(?<![(\\w])1\\)\\s,
'su',
)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.
(regexp-non-literal-typescript)
admin/pipeline/body/form-sections.ts
[warning] 179-179: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(—?${pattern}, 'gu')
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
admin/pipeline/body/review.ts
[warning] 318-321: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(
<a\\b[^>]*data-ref="${escapeRegExp(item)}"[^>]*>([^<]*)</a>,
'u',
)
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
🪛 Biome (2.5.6)
admin/pipeline/body/migrate-dry.ts
[error] 11-11: The import specifier ajv cannot be resolved: module not found
(lint/correctness/noUnresolvedImports)
[error] 12-12: The import specifier ajv/dist/2020 cannot be resolved: module not found
(lint/correctness/noUnresolvedImports)
admin/pipeline/body/dry-run-report.ts
[error] 10-10: The import specifier ajv cannot be resolved: module not found
(lint/correctness/noUnresolvedImports)
admin/pipeline/body/dry-run.ts
[error] 14-14: The import specifier ajv cannot be resolved: module not found
(lint/correctness/noUnresolvedImports)
[error] 15-15: The import specifier ajv/dist/2020 cannot be resolved: module not found
(lint/correctness/noUnresolvedImports)
🪛 GitHub Check: Lint
admin/pipeline/body/fixtures/extract.ts
[notice] 10-382: lint/style/noExcessiveLinesPerFile
This file has too many lines (363). Maximum allowed is 300.
admin/pipeline/body/dry-run.test.ts
[notice] 191-191: lint/complexity/noExcessiveCognitiveComplexity
Excessive complexity of 19 detected (max: 15).
[notice] 99-99: lint/style/useDestructuring
Use array destructuring instead of accessing array elements by index.
[notice] 96-96: lint/style/useDestructuring
Use array destructuring instead of accessing array elements by index.
[notice] 1-328: lint/style/noExcessiveLinesPerFile
This file has too many lines (328). Maximum allowed is 300.
admin/pipeline/body/dry-run-verify.ts
[notice] 166-166: lint/style/useExplicitLengthCheck
Use .length > 0 when checking .length is not zero.
admin/pipeline/body/census.ts
[notice] 63-63: lint/nursery/useNamedCaptureGroup
Capture group is not named.
[notice] 444-444: lint/complexity/noExcessiveCognitiveComplexity
Excessive complexity of 20 detected (max: 15).
[notice] 88-88: lint/correctness/useSingleJsDocAsterisk
JSDoc comment line should start with a single asterisk.
[notice] 9-609: lint/style/noExcessiveLinesPerFile
This file has too many lines (562). Maximum allowed is 300.
🪛 GitHub Check: SonarCloud Code Analysis
admin/pipeline/body/lettered.test.ts
[warning] 202-202: Prefer "expect(entries).toHaveLength(9)" over this generic assertion for better reporting; it works on any object with a numeric length property.
admin/pipeline/body/form-sections.test.ts
[warning] 262-262: Prefer "expect(entries).toHaveLength(9)" over this generic assertion for better reporting; it works on any object with a numeric length property.
[warning] 236-236: Prefer "expect(entries).toHaveLength(25)" over this generic assertion for better reporting; it works on any object with a numeric length property.
admin/pipeline/body/lettered.ts
[warning] 106-106: Prefer String.fromCodePoint() over String.fromCharCode().
admin/pipeline/body/migrate-dry.ts
[warning] 106-106: Prefer String#replaceAll() over String#split().join().
[warning] 79-79: The non-empty check is useless as Array#some() returns false for an empty array.
admin/pipeline/body/dry-run.test.ts
[warning] 122-122: Prefer "expect(body.senses).toHaveLength(e.content.senses.length)" over this generic assertion for better reporting; it works on any object with a numeric length property.
[warning] 29-29: Prefer "expect(entries).toHaveLength(3)" over this generic assertion for better reporting; it works on any object with a numeric length property.
admin/pipeline/body/census.ts
[warning] 242-242: String.raw should be used to avoid escaping \.
[warning] 406-406: Replace this character class by the character itself.
[warning] 367-367: Prefer using an optional chain expression instead, as it's more concise and easier to read.
[failure] 444-444: Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.
[warning] 25-25: Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.
[warning] 242-242: String.raw should be used to avoid escaping \.
admin/pipeline/body/repairs.test.ts
[warning] 66-66: Prefer "expect(entry.content.senses).toHaveLength(source.content.senses.length - 1)" over this generic assertion for better reporting; it works on any object with a numeric length property.
admin/pipeline/body/form-sections.ts
[warning] 178-178: String.raw should be used to avoid escaping \.
[warning] 179-179: Prefer String#replaceAll() over String#replace().
[warning] 178-178: Prefer String#replaceAll() over String#replace().
[warning] 176-176: String.raw should be used to avoid escaping \.
[warning] 179-179: String.raw should be used to avoid escaping \.
admin/pipeline/body/review.ts
[warning] 107-107: String.raw should be used to avoid escaping \.
[warning] 320-320: String.raw should be used to avoid escaping \.
[warning] 85-85: Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.
[warning] 105-105: String.raw should be used to avoid escaping \.
admin/pipeline/body/repairs.ts
[warning] 17-17: Complete the task associated to this "TODO" comment.
[warning] 484-484: Prefer String#replaceAll() over String#split().join().
🪛 LanguageTool
docs/v2/body-review/01-broken-sequences.md
[grammar] ~80-~80: Ensure spelling is correct
Context: ... --- | | A00675 | אוּלָם II | 2 | …eub. Géogr. p. 18; 261) Ulam (Porta) a place in Gi...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~80-~80: Ensure spelling is correct
Context: ...place in Gilead, and one in Galilee. Y. Snh. X, 28ᵈ —2) | ```p. 18; 261) Ula...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~81-~81: Ensure spelling is correct
Context: ... CXXXIII, 2. Targ. Y. Ex. XXVI, 4 (Var. אֶימְרָא). V. next w. —4) | ```(Sarah) not eve...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~83-~83: Ensure spelling is correct
Context: ...i>, 1) homiletic``` (Verified via print endition) | | B01321 | בַּרְקַאי II | 2 | , v. ב...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~89-~89: Ensure spelling is correct
Context: ...s), v. אֶחָד. Cant. R. l. c.; a. fr. V. דָּבָר. —2) | I believe the existing 2) se...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~89-~89: Ensure spelling is correct
Context: ...he existing 2) sense in source data, is actualy a second sense of the plural with an im...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~90-~90: Ensure spelling is correct
Context: ...7ᵇ, v. אֲרָם; a. fr.—M. Kat. III, 3, v. גָּזָר. —4) | ```precipice.—2) decree, edi...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~95-~95: Ensure spelling is correct
Context: ...—7)**
… R. to VII, 7 [read:] הרי הוא כּוֹבְשֵׁנִי וכ׳ behold, he is attacking me in thy p...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~95-~95: Ensure spelling is correct
Context: ...is entry ruins my theory about Pl being a seperatley numberd section | | M00252 | מִדָּה | 1, 2, 4 |...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~100-~100: Ensure spelling is correct
Context: ...scratching a sore. Sabb. V, 4 (54ᵇ), v. לוֹעָא. —3) | kings; a. fr.—2) a yoke | | ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~106-~106: Ensure spelling is correct
Context: ...4; Y. ib. 36ᵃ top צִילְעוֹת constr., v. פּוּאָה. —3) | es; a. fr.—2) side | | Q0197...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~109-~109: Ensure spelling is correct
Context: ...h. text מוֹט). Targ. Y. II ib. XIII, 23 קוֹפָה. —2)
…old trunk.—Pl. קוֹפָאֵי. B...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~111-~111: Consider a more concise word here.
Context: ...r. IX, 14ᵇ —2)
…res only rinsing in order to be restored to Levitical cleanness. Ḥul...
(IN_ORDER_TO_PREMIUM)
[style] ~113-~113: To form a complete sentence, be sure to include a subject.
Context: ...ext - s. 85; a. fr.— Absalom’s sister. should be... s. 85; a. fr.—2) Absalom’s sister...
(MISSING_IT_THERE)
[style] ~115-~115: To make your text as clear as possible to all readers, do not use this foreign term. Possible alternatives are “above”, “above-mentioned”, “aforementioned”, or “as previously mentioned” (in the document).
Context: ... | Hifil missing sense 4 v. supra.—4) to produce | | A01194 | אֵיזֶה ...
(SUPRA)
[style] ~121-~121: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...to the location in the text they go, so maybe a markup tag as well? These would not ...
(REP_MAYBE)
[style] ~121-~121: In American English, abbreviations like “etc.” require a period.
Context: ...o the source data due to import errors, etc, only deviations from the printed text....
(ETC_PERIOD)
[grammar] ~132-~132: Ensure spelling is correct
Context: ...on as note 1. The fact that sense 2 is labled *2 says to me there is a specific somet...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/v2/body-review/02-orphan-refs.md
[grammar] ~25-~25: Ensure spelling is correct
Context: ..."ת** . Sabb. 104ᵃ גוֹפו טימא אר̇חם עליו thoug… | | | C01225 | גֵּר | Jastrow, ג"ר 1 |...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~32-~32: Ensure spelling is correct
Context: ... …s of three letters each (Dan. V, 25). Snh. 22ᵃ; Cant. R. to III, 4; v. אאלר"ן...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~50-~50: Ensure spelling is correct
Context: ...ef. ib. IX (VI), 18. Mikv. VI, 1 עוּקַת המערה… | ALL Approved | | P00331 | עוּקָה | Er...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~51-~51: Ensure spelling is correct
Context: ...ef. ib. IX (VI), 18. Mikv. VI, 1 עוּקַת המערה… | | | P00331 | עוּקָה | Eruvin 88b:22 ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~52-~52: Ensure spelling is correct
Context: ...ef. ib. IX (VI), 18. Mikv. VI, 1 עוּקַת המערה… | | | P01404 | עֶרֶס | Targum Jerusale...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~54-~54: Ensure spelling is correct
Context: ...the minor transgressions: omission of a positi… | | ## Class 3 — unexplained, eyes-on...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~65-~65: ‘The situation of’ might be wordy. Consider a shorter alternative.
Context: ...ikhvar, Makhvar, a district of Peraea. [The situation of Machaerus forbids its identification wi...
(EN_WORDINESS_PREMIUM_THE_SITUATION_OF)
[grammar] ~68-~68: Ensure spelling is correct
Context: ...e idea linkage, but for us, we are only concered with showing what Jastow linked.
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/v2/body-review/07-italic-lettered-markers.md
[style] ~22-~22: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...…s. סָמוּי; f. סְמוּיָה, סְמוּיָיה; pl. סְמוּיִים, סְמוּיִין; סְמוּיוֹת `a...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~27-~27: Ensure spelling is correct
Context: ...man body, sensuality. Lev. R. s. 13, v. נָשַׁף. Ber. 17ᵃ גלוי … … | | | P00680 | עֵיר...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~28-~28: Ensure spelling is correct
Context: ... 17ᵃ גלוי … … | | | P00680 | עֵירוּב | …hich the legal fiction of community or conti...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~31-~31: To make your text as clear as possible to all readers, do not use this foreign term. Possible alternatives are “above”, “above-mentioned”, “aforementioned”, or “as previously mentioned” (in the document).
Context: ...ז. Bekh. 43ᵇ bot.; Sifra Emor l. c., v. supra.—Part. pass. מוּפְלָג <i>a</i>) remov...
(SUPRA)
[style] ~32-~32: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... …art. pass. פְּלִיג; f. פְּלִיגָא; pl. פְּלִיגִין, פְּלִיגֵי; פְּלִיגָן `a</i...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~33-~33: Ensure spelling is correct
Context: ...ה <i>a</i>) free, disengaged, single. Yeb. III, 5 שלשה אחין … ואחד מ׳ three broth...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~36-~36: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... | …t. pass. פָּסוּל; f. פְּסוּלָה; pl. פְּסוּלִים, פְּסוּלִין; פְּסוּלוֹת `a<...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~40-~40: Ensure spelling is correct
Context: ....—b) wings.… | | | P00856 | עָמַך II | …hat from him should rise priests and kings;...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~41-~41: Ensure spelling is correct
Context: ... trnsf. <i>a</i>) to be undecided. Y. Snh. V, end, 23ᵃ שלא ייראה דין זה יוצא מעמע...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~43-~43: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...….—Part. pass. עָקוּר; f. עֲקוּרָה; pl. עֲקוּרִים, עְקוּרִין; עֲקוּרוֹת `a...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~46-~46: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...s. Part. pass. צָמִיד; f. צְמִידָא; pl. צְמִידִין, <i>a</i>) attached, harnesse...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~52-~52: Ensure spelling is correct
Context: ...btful, v. צָרִיךְ. Y. Gitt. IV, 46ᵃ, v. אפרכוריס. Y. … | | | S00057 | קָבַל I | …. fr.—...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~54-~54: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ח | … pass. פְּתִיחַ; f. פְּתִיחָא; pl. פְּתִיחִין, פְּתִיחַיָּא; פְּתִיחָן `a...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~57-~57: Ensure spelling is correct
Context: ... Ex. IX, … | | | S00123 | קְדוּשָּׁה | …hould be performed with less than ten persons...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~63-~63: Ensure spelling is correct
Context: ...Targ. Is. VII, 18 (?).—b) restrictions. Yeb. 107ᵇ תר… | | | S01725 | קָפַח | …ot a...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~68-~68: Ensure spelling is correct
Context: ...at one time. Ḥag. 13ᵃ רָאשֵׁי פרקים, v. פֶּרֶק; a. fr.—Trnsf. <i>a</i>) chief, magistrate, leader, ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~72-~72: Ensure spelling is correct
Context: ...X, 16) to have connection with a beast. Snh. I, 4 … | | | T00137 | רָבַץ | … a loa...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~80-~80: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...art. pass. מוּתְאָם; f. מוּתְאֶמֶת; pl. מוּתְאָמִים; מוּתְאָמוֹת <i>a</i>) place...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~83-~83: Ensure spelling is correct
Context: ...rbal communication, oral study, opp. to מִשְׁנ… | | | U01137 | שָׁכַח | …ose it served...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~88-~88: Consider a more concise word here.
Context: ...| | | U01525 | שָׁמַר | …s been closed in order to preserve the flavor).—Part. pass. מְשׁו...
(IN_ORDER_TO_PREMIUM)
[grammar] ~89-~89: Ensure spelling is correct
Context: ...ובא מן המזיקי… | | | U01589 | שֵׁנִי | …irect from the fire.—Maas. Sh. I, 1, a. fr. מ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~93-~93: Ensure spelling is correct
Context: ...שָׂה &c. <i>a</i>) (cmp. אָחוּז s. v. אָחַז) holding. Y. Taan. l. c. היה משה ת׳ בטפחיים M… | ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~94-~94: Consider an alternative adverb to strengthen your wording.
Context: ... מְתוּקָּנִין; מְתוּקָּנוֹת <i>a</i>) properly prepared, proper, good, right. Bets. 34...
(PROPERLY_THOROUGHLY)
[style] ~94-~94: To make your text as clear as possible to all readers, do not use this foreign term. Possible alternatives are “above”, “above-mentioned”, “aforementioned”, or “as previously mentioned” (in the document).
Context: ...red, proper, good, right. Bets. 34ᵇ, v. supra. Erub. 32ᵃ… | | | V00905 | תָּקַע | … ...
(SUPRA)
docs/v2/body-review/04-label-quarantines.md
[grammar] ~16-~16: Ensure spelling is correct
Context: ...his implies. Likely should move to the begining of the sense text to keep the notation…...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~20-~20: To make your text as clear as possible to all readers, do not use this foreign term. Possible alternatives are “above”, “above-mentioned”, “aforementioned”, or “as previously mentioned” (in the document).
Context: ... | | | U00745 | שטי | -2) | same, v. supra. -2) (with ב) to fool, jest. Yeb. 1...
(SUPRA)
[grammar] ~20-~20: Ensure spelling is correct
Context: ... supra. -2) (with ב) to fool, jest. Yeb. 106ᵃ; B. Kam. 116ᵃ אמר ליה משטה אני בך...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~21-~21: Ensure spelling is correct
Context: ... מִשְׁלַחַת) letting loose, visitation. Yeb. 114ᵇ ש׳ נחשים וכ׳ a plague of serpents...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/v2/body-review/03-quotes-stragglers.md
[grammar] ~16-~16: Ensure spelling is correct
Context: ... with many cases, trader’s chest. Tanḥ. B’midb. 20 לאדם פרגמטיוטיס שהיה לו א׳ של זכוכי...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~19-~19: Ensure spelling is correct
Context: ...׳ נוגהא Venus. Targ. II Esth. II, 7 (v. אִיסְתִּירָא); Yalk. Esth. 1053 (hebr.), v. אִסְתְּהַר.—Sabb...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~19-~19: Ensure spelling is correct
Context: ... 7 (v. אִיסְתִּירָא); Yalk. Esth. 1053 (hebr.), v. אִסְתְּהַר.—Sabb. l. c.; a. e.—כ׳...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~23-~23: Ensure spelling is correct
Context: ..., it was never validated by them so not supprised has these.
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/v2/body-review/05-unit-segmentation-sample.md
[grammar] ~87-~87: Ensure spelling is correct
Context: ... בִּצְעִים, בִּצְעִין, בִּי׳. - Tosef. Snh. III, 4 שתי בצעין ed. Zuck. (Var. ביצוע...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~89-~89: Ensure spelling is correct
Context: ...המים between the dykes (of the Nile). - Snh. 96ᵃ בִּיצְעֵי וכ׳. - Ib. 5ᵇ, v. בִּצָּ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~99-~99: Ensure spelling is correct
Context: ...ing than when open). - Ab. Zar. 60ᵃ, v. כּוּבָּא II. - Sabb. 157ᵇ, v. אוּדְנָא II. **Decisi...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~100-~100: Ensure spelling is correct
Context: .... 60ᵃ, v. כּוּבָּא II. - Sabb. 157ᵇ, v. אוּדְנָא II. Decision: ### C00432 — גּוֹנֶבֶת **G...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~160-~160: Ensure spelling is correct
Context: ... וכ׳ a bale filled with fruit stones. - Ukts. II, 2, v. חוֹתָם.—[Y. Keth. VIII, 32ᵇ ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~210-~210: Ensure spelling is correct
Context: ... ומ׳ ידעינן וכ׳ and how do we know &c.? Snh. 61ᵇ מ׳ אמינא לה whence (on what eviden...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~244-~244: Ensure spelling is correct
Context: ... and he who presses him (the stranger), contrad. to אִנָּה.—Part. pass. לָחוּץ, pl. לְח...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~330-~330: Ensure spelling is correct
Context: ... estimate yield five S’ah of coal. - Y. Snh. IX, 27ᵃ bot. ע׳ של טעות an erroneous p...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~331-~331: Ensure spelling is correct
Context: ...s. - Y. Naz. IX, end, 58ᵃ ע׳ האמצעי, v. אוּמָד. - Ib. עֶמֶד, a. עֲמָדָה.—Pl. עוּמָדִין...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~356-~356: Ensure spelling is correct
Context: ...k. VII, beg. 51ᵃ, a. e. לוקח מן הפ׳, v. סִידְקִי. - Y. Shebi. VII, 37ᶜ top ובלבד שלא יעש...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~375-~375: Ensure spelling is correct
Context: ...grieved. - Targ. Lam. IV, 1 (ed. Amst. עַמָּא). - Targ. O. Lev. XIII, 6; 56 עָמָא ed. B...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~378-~378: Ensure spelling is correct
Context: .... (ed. Lag. ותעימי, read ותִיעֲמֵי; Ar. ויִתְעֲמֵי, Ithpe.).— - Targ. Is. LIX, 11 עָמֵינָא (ed. Lag. עמנא; ed...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~410-~410: Ensure spelling is correct
Context: .... - B. Mets. V, 10 הקור (corr. acc.). - Snh. 20ᵇ קוּדּוֹ Ms. M. his bowl (was all t...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~418-~418: Ensure spelling is correct
Context: ...assacre. - Targ. Is. XXII, 5 (ed. Wil. קְטוֹל). - Ib. XXX, 25 (ed. Wil. קְטוֹל). **Dec...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~436-~436: ‘on account of’ might be wordy. Consider a shorter alternative.
Context: ... once שאובה) (the bath is disqualified) on account of the drawn water which is distinguishabl...
(EN_WORDINESS_PREMIUM_ON_ACCOUNT_OF)
[grammar] ~445-~445: Ensure spelling is correct
Context: ...M. (ed. דרא, transp.), v. אָסָא III.—V. רָדַיָּא. Decision: ### S02160 — קַרְקוּזָאָה ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~453-~453: Ensure spelling is correct
Context: ...1ᵃ (expl. דלעת הרמוצ׳) קרי ק׳ (not קרא) Ḳarḳuz pumpkins. Decision: ### U00704 — שָׁחַר I **Gl...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~481-~481: Ensure spelling is correct
Context: ...B. Bath. 37ᵇ האי מאן … בשִׁיפּוּדֵיה עד וכ׳ Ar. (ed. משיפוליה) if one sells a palm tree...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/v2/body-census.md
[style] ~49-~49: ‘within reach of’ might be wordy. Consider a shorter alternative.
Context: ...er vocabulary is small and closed, well within reach of an exhaustive parse table rather than a...
(EN_WORDINESS_PREMIUM_WITHIN_REACH_OF)
docs/specs/2026-07-11-entry-body-model-design.md
[locale-violation] ~105-~105: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ...ong boundaries are per-entry hand fixes afterwards | | stems | Binyan sections (upstream...
(AFTERWARDS_US)
docs/v2/sefaria-report.md
[style] ~211-~211: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...לָּא"], "verbal_stem": "Ithpa." } ``` (Note also the leading space on the second form — ...
(ALSO_PLACEMENT)
docs/superpowers/plans/2026-07-11-entry-body-model.md
[uncategorized] ~1250-~1250: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...y-run reports and the source, emits the markdown tables listed in the AC (same streaming...
(MARKDOWN_NNP)
🪛 markdownlint-cli2 (0.23.2)
docs/v2/body-review/01-broken-sequences.md
[warning] 81-81: Spaces inside code span elements
(MD038, no-space-in-code)
[warning] 88-88: Spaces inside code span elements
(MD038, no-space-in-code)
[warning] 88-88: Spaces inside code span elements
(MD038, no-space-in-code)
[warning] 91-91: Spaces inside code span elements
(MD038, no-space-in-code)
[warning] 132-132: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
docs/v2/body-review/02-orphan-refs.md
[warning] 68-68: Files should end with a single newline character
(MD047, single-trailing-newline)
docs/v2/body-review/06-empty-binyan-forms.md
[warning] 37-37: Files should end with a single newline character
(MD047, single-trailing-newline)
docs/v2/body-review/05-unit-segmentation-sample.md
[warning] 17-17: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3
(MD001, heading-increment)
docs/v2/sefaria-report.md
[warning] 292-292: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 300-300: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
docs/superpowers/plans/2026-07-11-entry-body-model.md
[warning] 28-28: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 OpenGrep (1.26.0)
admin/pipeline/body/labels.ts
[ERROR] 55-55: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
admin/pipeline/body/migrate-dry.ts
[ERROR] 74-74: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
admin/pipeline/body/cite.ts
[ERROR] 47-47: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 55-55: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 66-66: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 81-81: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 96-96: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 110-110: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 123-123: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 134-134: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
admin/pipeline/body/census.ts
[ERROR] 70-70: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
admin/pipeline/body/review.ts
[ERROR] 323-323: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
[ERROR] 710-710: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
admin/pipeline/body/repairs.ts
[ERROR] 475-475: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
| function censusEntry(entry: SourceEntry, acc: Accumulator): void { | ||
| acc.entries++; | ||
| const marker = entry.content.morphology; | ||
| if (marker !== undefined) { | ||
| acc.markers.set(marker, (acc.markers.get(marker) ?? 0) + 1); | ||
| } | ||
|
|
||
| let hasLettered = false; | ||
| let hasPluralSection = false; | ||
| const hitMarkers = new Set<string>(); | ||
| for (const sense of walkSenses(entry.content.senses)) { | ||
| if (sense.definition !== undefined) { | ||
| acc.definitions++; | ||
| } | ||
| const definition = sense.definition ?? ''; | ||
| if (letteredRun(definition)) { | ||
| hasLettered = true; | ||
| } | ||
| if (pluralSection(definition)) { | ||
| hasPluralSection = true; | ||
| } | ||
| for (const formMarker of formSectionCandidates(definition)) { | ||
| hitMarkers.add(formMarker); | ||
| } | ||
| const hits = findCitations(definition); | ||
| tallyCitations(hits, acc.citations); | ||
| tallyBoundaries(definition, hits, acc.boundaries); | ||
| tallyIbid(definition, hits, acc.ibid); | ||
| } | ||
| if (hasLettered) { | ||
| acc.lettered.add(entry.rid); | ||
| } | ||
| if (hasPluralSection) { | ||
| acc.pluralSections.add(entry.rid); | ||
| } | ||
| for (const formMarker of hitMarkers) { | ||
| acc.formSections.get(formMarker)?.add(entry.rid); | ||
| } | ||
|
|
||
| // Sequence numbering is only checked at the top level: nested | ||
| // sub-senses (e.g. under a grammar node) commonly restart their own | ||
| // numbering, so folding them into one flat sequence manufactures | ||
| // false breaks that don't exist in the source. | ||
| tallySequence( | ||
| entry.rid, | ||
| entry.content.senses, | ||
| { | ||
| ...(entry.language_code !== undefined && { | ||
| languageCode: entry.language_code, | ||
| }), | ||
| ...(entry.language_reference !== undefined && { | ||
| languageReference: entry.language_reference, | ||
| }), | ||
| ...(entry.content.morphology !== undefined && { | ||
| morphology: entry.content.morphology, | ||
| }), | ||
| }, | ||
| acc.brokenSequences, | ||
| ); | ||
|
|
||
| const opener = classifyOpener(entry.content.senses[0]?.definition ?? ''); | ||
| acc.preambleOpeners.set(opener, (acc.preambleOpeners.get(opener) ?? 0) + 1); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Reduce the complexity of censusEntry to clear the quality gate.
SonarQube reports a gate failure at this function (cognitive complexity 16 vs 15 allowed), and Biome reports lint/complexity/noExcessiveCognitiveComplexity with a measured complexity of 20. Extract the per-sense loop into a helper. The helper returns the per-entry flags, and censusEntry keeps only the accumulator updates.
♻️ Proposed refactor sketch
+function censusSenses(
+ entry: SourceEntry,
+ acc: Accumulator,
+): { hasLettered: boolean; hasPluralSection: boolean; hitMarkers: Set<string> } {
+ let hasLettered = false;
+ let hasPluralSection = false;
+ const hitMarkers = new Set<string>();
+ for (const sense of walkSenses(entry.content.senses)) {
+ if (sense.definition !== undefined) {
+ acc.definitions++;
+ }
+ const definition = sense.definition ?? '';
+ hasLettered = hasLettered || letteredRun(definition);
+ hasPluralSection = hasPluralSection || pluralSection(definition);
+ for (const formMarker of formSectionCandidates(definition)) {
+ hitMarkers.add(formMarker);
+ }
+ const hits = findCitations(definition);
+ tallyCitations(hits, acc.citations);
+ tallyBoundaries(definition, hits, acc.boundaries);
+ tallyIbid(definition, hits, acc.ibid);
+ }
+ return { hasLettered, hasPluralSection, hitMarkers };
+}
+
function censusEntry(entry: SourceEntry, acc: Accumulator): void {
acc.entries++;
const marker = entry.content.morphology;
if (marker !== undefined) {
acc.markers.set(marker, (acc.markers.get(marker) ?? 0) + 1);
}
-
- let hasLettered = false;
- let hasPluralSection = false;
- const hitMarkers = new Set<string>();
- for (const sense of walkSenses(entry.content.senses)) {
- if (sense.definition !== undefined) {
- acc.definitions++;
- }
- const definition = sense.definition ?? '';
- if (letteredRun(definition)) {
- hasLettered = true;
- }
- if (pluralSection(definition)) {
- hasPluralSection = true;
- }
- for (const formMarker of formSectionCandidates(definition)) {
- hitMarkers.add(formMarker);
- }
- const hits = findCitations(definition);
- tallyCitations(hits, acc.citations);
- tallyBoundaries(definition, hits, acc.boundaries);
- tallyIbid(definition, hits, acc.ibid);
- }
+ const { hasLettered, hasPluralSection, hitMarkers } = censusSenses(entry, acc);
if (hasLettered) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function censusEntry(entry: SourceEntry, acc: Accumulator): void { | |
| acc.entries++; | |
| const marker = entry.content.morphology; | |
| if (marker !== undefined) { | |
| acc.markers.set(marker, (acc.markers.get(marker) ?? 0) + 1); | |
| } | |
| let hasLettered = false; | |
| let hasPluralSection = false; | |
| const hitMarkers = new Set<string>(); | |
| for (const sense of walkSenses(entry.content.senses)) { | |
| if (sense.definition !== undefined) { | |
| acc.definitions++; | |
| } | |
| const definition = sense.definition ?? ''; | |
| if (letteredRun(definition)) { | |
| hasLettered = true; | |
| } | |
| if (pluralSection(definition)) { | |
| hasPluralSection = true; | |
| } | |
| for (const formMarker of formSectionCandidates(definition)) { | |
| hitMarkers.add(formMarker); | |
| } | |
| const hits = findCitations(definition); | |
| tallyCitations(hits, acc.citations); | |
| tallyBoundaries(definition, hits, acc.boundaries); | |
| tallyIbid(definition, hits, acc.ibid); | |
| } | |
| if (hasLettered) { | |
| acc.lettered.add(entry.rid); | |
| } | |
| if (hasPluralSection) { | |
| acc.pluralSections.add(entry.rid); | |
| } | |
| for (const formMarker of hitMarkers) { | |
| acc.formSections.get(formMarker)?.add(entry.rid); | |
| } | |
| // Sequence numbering is only checked at the top level: nested | |
| // sub-senses (e.g. under a grammar node) commonly restart their own | |
| // numbering, so folding them into one flat sequence manufactures | |
| // false breaks that don't exist in the source. | |
| tallySequence( | |
| entry.rid, | |
| entry.content.senses, | |
| { | |
| ...(entry.language_code !== undefined && { | |
| languageCode: entry.language_code, | |
| }), | |
| ...(entry.language_reference !== undefined && { | |
| languageReference: entry.language_reference, | |
| }), | |
| ...(entry.content.morphology !== undefined && { | |
| morphology: entry.content.morphology, | |
| }), | |
| }, | |
| acc.brokenSequences, | |
| ); | |
| const opener = classifyOpener(entry.content.senses[0]?.definition ?? ''); | |
| acc.preambleOpeners.set(opener, (acc.preambleOpeners.get(opener) ?? 0) + 1); | |
| } | |
| function censusSenses( | |
| entry: SourceEntry, | |
| acc: Accumulator, | |
| ): { hasLettered: boolean; hasPluralSection: boolean; hitMarkers: Set<string> } { | |
| let hasLettered = false; | |
| let hasPluralSection = false; | |
| const hitMarkers = new Set<string>(); | |
| for (const sense of walkSenses(entry.content.senses)) { | |
| if (sense.definition !== undefined) { | |
| acc.definitions++; | |
| } | |
| const definition = sense.definition ?? ''; | |
| hasLettered = hasLettered || letteredRun(definition); | |
| hasPluralSection = hasPluralSection || pluralSection(definition); | |
| for (const formMarker of formSectionCandidates(definition)) { | |
| hitMarkers.add(formMarker); | |
| } | |
| const hits = findCitations(definition); | |
| tallyCitations(hits, acc.citations); | |
| tallyBoundaries(definition, hits, acc.boundaries); | |
| tallyIbid(definition, hits, acc.ibid); | |
| } | |
| return { hasLettered, hasPluralSection, hitMarkers }; | |
| } | |
| function censusEntry(entry: SourceEntry, acc: Accumulator): void { | |
| acc.entries++; | |
| const marker = entry.content.morphology; | |
| if (marker !== undefined) { | |
| acc.markers.set(marker, (acc.markers.get(marker) ?? 0) + 1); | |
| } | |
| const { hasLettered, hasPluralSection, hitMarkers } = censusSenses(entry, acc); | |
| if (hasLettered) { | |
| acc.lettered.add(entry.rid); | |
| } | |
| if (hasPluralSection) { | |
| acc.pluralSections.add(entry.rid); | |
| } | |
| for (const formMarker of hitMarkers) { | |
| acc.formSections.get(formMarker)?.add(entry.rid); | |
| } | |
| // Sequence numbering is only checked at the top level: nested | |
| // sub-senses (e.g. under a grammar node) commonly restart their own | |
| // numbering, so folding them into one flat sequence manufactures | |
| // false breaks that don't exist in the source. | |
| tallySequence( | |
| entry.rid, | |
| entry.content.senses, | |
| { | |
| ...(entry.language_code !== undefined && { | |
| languageCode: entry.language_code, | |
| }), | |
| ...(entry.language_reference !== undefined && { | |
| languageReference: entry.language_reference, | |
| }), | |
| ...(entry.content.morphology !== undefined && { | |
| morphology: entry.content.morphology, | |
| }), | |
| }, | |
| acc.brokenSequences, | |
| ); | |
| const opener = classifyOpener(entry.content.senses[0]?.definition ?? ''); | |
| acc.preambleOpeners.set(opener, (acc.preambleOpeners.get(opener) ?? 0) + 1); | |
| } |
🧰 Tools
🪛 GitHub Check: Lint
[notice] 444-444: lint/complexity/noExcessiveCognitiveComplexity
Excessive complexity of 20 detected (max: 15).
🪛 GitHub Check: SonarCloud Code Analysis
[failure] 444-444: Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@admin/pipeline/body/census.ts` around lines 444 - 506, Reduce cognitive
complexity in censusEntry by extracting the walkSenses per-sense
processing—including definition counting, lettered and plural detection,
form-marker collection, and citation/boundary/ibid tallying—into a helper. Have
the helper return the per-entry flags and collected form markers, then leave
censusEntry responsible only for applying those results to the accumulator and
retaining the existing sequence and opener handling.
Sources: Coding guidelines, Linters/SAST tools
| function findCitations(text: string): CitationHit[] { | ||
| if (!text.includes('</a>')) { | ||
| return []; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Unterminated anchors are never emitted, which breaks the stated contract. The contract at Lines 6-9 promises one hit per refLink open tag, with malformed: true when no </a> follows. Two sites drop the hit instead: the fast path returns early when the text holds no </a> at all, and the boundary loop breaks when nothing follows the open tag. census.ts tallyCitations therefore undercounts the recoveredLoss damage class it measures.
admin/pipeline/body/cite.ts#L89-L92: gate the fast path onclass="refLink"instead of</a>, so the scan still runs when no close tag exists.admin/pipeline/body/cite.ts#L114-L118: push{ ...hit, malformed: true }before thebreak, the same way the nested-open branch at Lines 132-134 does.
📍 Affects 1 file
admin/pipeline/body/cite.ts#L89-L92(this comment)admin/pipeline/body/cite.ts#L114-L118
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@admin/pipeline/body/cite.ts` around lines 89 - 92, Update findCitations in
admin/pipeline/body/cite.ts at lines 89-92 to gate the fast path on the presence
of class="refLink" rather than </a>, so open tags are scanned without closing
tags; at lines 114-118, push the current hit with malformed: true before
breaking when no closing content follows the open tag, matching the nested-open
handling.
| | S00252 | קוֹדַשׁ | `[[null,"קודש קוֹדַשׁ",null]]` | ch. same holiness, sanctuary &c. Targ. Ex. XXIX, 29. Targ. Ps. LI, 13. Targ. Ex. XXVIII, 29; a. fr.—Pl. קוּדְשִׁין, קוּדְשַׁיָּא. Targ. Lev. XXI, 22. Ib. XXII, 2; a. fr.—קודש ק׳ the Holy of Holies. Targ. Ex. XXVI, 33; a. fr. the Holiness, the Lord, usu. with בריך הוא (abbrev. קב"ה), v. קָדוֹשׁ. Targ. Y. Num. XXI, 34. Targ. Y. Gen. XXV, 21; a. fr.—Ber. 7ᵃ ומי… | | | ||
| | S01101 | *קיפוסולין | `[[null,"בקיפוסולין של מצרים וכ׳","Joseph was buried in (the necropolis of) Thebes"]]` | , prob. to be read: קְיוֹסְפּוֹלִין (a perversion of דְּיוֹסְפּוֹלִין; cmp. קאניסין) Diospolis; ק׳ של מצרים Diospolis in Egypt = Thebes. Mekh. B’shall., s. 1 בק׳ של מצרים וכ׳ Joseph was buried in (the necropolis of) Thebes; (Tosef. Sot. IV, 7 בקברי מלכים; Ex. R. s. 20 בתוך הפלטורין וכ׳ in the palaces (tomb chambers) in the manner as kings were buried; v. קְב… | | | ||
|
|
||
| I confirmed with Sefaria Devs that the quotes field is a leftover from a previous design choice, it was never validated by them so not supprised has these. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the provenance note.
Change supprised to surprised. Prefer Sefaria developers over Sefaria Devs in this maintainer document.
🧰 Tools
🪛 LanguageTool
[grammar] ~23-~23: Ensure spelling is correct
Context: ..., it was never validated by them so not supprised has these.
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/v2/body-review/03-quotes-stragglers.md` at line 23, Update the
provenance note to use “Sefaria developers” instead of “Sefaria Devs” and
correct the typo “supprised” to “surprised,” preserving the rest of the note.
Source: Linters/SAST tools
| ## 6. Duplicated nested anchors (475 anchors) | ||
|
|
||
| Identical anchors nested one inside the other. | ||
|
|
||
| **Example — `A00085`:** | ||
|
|
||
| ```html | ||
| <a … href="/Jastrow,_אבהנוס.1" data-ref="Jastrow, אבהנוס 1"><a … href="/Jastrow,_אבהנוס.1" data-ref="Jastrow, אבהנוס 1">אבהנוס</a></a> | ||
| ``` | ||
|
|
||
| **Fix:** drop the outer duplicate. **Detection:** `<a` immediately | ||
| followed by another `<a` with identical `href`/`data-ref`. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Use one scoped duplicate-anchor metric.
The files report 475 and 1,230 anchors. The complete register value is 475 definition anchors plus 755 language_reference anchors. Make the scope explicit or update both documents to the same total.
docs/v2/sefaria-report.md#L156-L167: label 475 as definitions-only or report 1,230.docs/v2/upstream-issues.md#L21-L21: retain the 1,230 total only with the all-field scope stated.
📍 Affects 2 files
docs/v2/sefaria-report.md#L156-L167(this comment)docs/v2/upstream-issues.md#L21-L21
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/v2/sefaria-report.md` around lines 156 - 167, The duplicated
nested-anchor metric must use an explicit scope consistently: in
docs/v2/sefaria-report.md lines 156-167, either label 475 as definition anchors
only or change it to the all-field total of 1,230; in docs/v2/upstream-issues.md
line 21, retain 1,230 only if the all-field scope, including 475 definition and
755 language_reference anchors, is stated.
| ``` | ||
| …from the mouth of the Lord.—Pl. גְּבוּרוֹת 1) manifestations of | ||
| Divine power, wonders. … —2) mighty deeds… | ||
| ``` | ||
|
|
||
| The `1)` and `2)` here are not sub-points of sense 3 — they are the | ||
| plural lemma's own senses. A faithful structure would be, in outline: | ||
|
|
||
| ``` | ||
| senses: 1) strength… 2) … 3) might of God… | ||
| plural (גְּבוּרוֹת): 1) manifestations of Divine power… 2) mighty deeds… | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add languages to both fenced code blocks.
Use text for the two examples. This fixes the MD040 warnings and keeps the report lint-clean.
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 292-292: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 300-300: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/v2/sefaria-report.md` around lines 292 - 303, Add the text language
identifier to both fenced code blocks in the documented examples, including the
block showing the current structure and the block showing the faithful
structure, while leaving their contents unchanged.
Source: Linters/SAST tools
27 comments triaged, each verified against code before acting. Code: - source: flush TextDecoder after the last chunk so a stream ending mid-multi-byte-sequence fails visibly instead of silently shortening the tail line - migrate-dry: contain repair drift per entry, list every failure in the report, rethrow after the walk (stays loud, one run reports all drifts); repairFailures in summary - repairs/migrate-dry: single walkSensesDeep (exported) - repairs.test: fixture paths via import.meta.dir (CWD-free) - labels.test: corpus sweep tallies while streaming - lettered.test: stale 5-entry docstring -> 9 - lint infos: named capture group, JSDoc asterisk, explicit length check, array destructuring Docs: - 00-INDEX: statuses awaiting review -> reviewed 2026-08-05 - 01: section-level decision paragraph (per design changelog); no-change rows noted as superseded by the split follow-up - 02/03/04: typo + grammar fixes in maintainer notes (meaning unchanged), final newline - body-migration: 129/3-sample -> 133/4; body-dryrun 60.8%; - body-census: lettered fixture is a reviewed 9-rid sample - sefaria-report: duplicate-anchor scope 475 vs 1,230 stated, fenced block language; upstream-issues #1 lists served AND print headword forms - tasks.json lastUpdated matches final revision Skipped with reasons (PR comment): cite.ts no-close fast path (pinned test, zero corpus incidence), buildStem loud-fail (dry-run reports via schemaFailures by contract), excessive- lines/complexity infos (accepted budget), bun version pin (CI concern), notes mechanism (tracked as issue #38). Signed-off-by: Brian L. <brian@uniquepixels.xyz>
CodeRabbit round-2 disposition (27 comments)Fixed in Skipped, with reasons (5):
The no-byte-change disposition class itself is superseded by the follow-up sense-structure-repair spec (maintainer ruling 2026-08-06); tracked on branch 🤖 Generated with Claude Code |
|
|
@coderabbitai review |
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@admin/pipeline/body/migrate-dry.ts`:
- Around line 235-239: Update the error message in the repairFailures handling
block to use “entry” when there is exactly one failure and “entries” when there
are multiple failures, instead of emitting the literal “entr(y/ies)” label.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 9a6e4855-e57b-4b84-9124-873293c132a7
📒 Files selected for processing (20)
admin/pipeline/body/census.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/lettered.test.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/repairs.tsadmin/pipeline/body/source.tsdocs/superpowers/plans/2026-07-11-entry-body-model.md.tasks.jsondocs/v2/body-census.mddocs/v2/body-dryrun.mddocs/v2/body-migration.mddocs/v2/body-review/00-INDEX.mddocs/v2/body-review/01-broken-sequences.mddocs/v2/body-review/02-orphan-refs.mddocs/v2/body-review/03-quotes-stragglers.mddocs/v2/body-review/04-label-quarantines.mddocs/v2/sefaria-report.mddocs/v2/upstream-issues.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Workers Builds: jastrow
⚠️ CI failures not shown inline (1)
GitHub Check: Workers Builds: jastrow: Workers Builds: jastrow
Conclusion: failure
Build ID: [c3edbe42-ee40-463f-ad83-ea05e7f32b19](https://dash.cloudflare.com/cf68e0017c53376defadebeecd91fda2/workers/services/view/jastrow/production/builds/c3edbe42-ee40-463f-ad83-ea05e7f32b19)
Script: [jastrow](https://dash.cloudflare.com/cf68e0017c53376defadebeecd91fda2/workers/services/view/jastrow/production)
🧰 Additional context used
📓 Path-based instructions (2)
**
⚙️ CodeRabbit configuration file
**: General project rules:
- This is a vanilla JS static site PWA. No bundler, no framework, no npm packages at runtime.
- All JS runs in the browser unless under
admin/(maintainer tooling, which uses Bun).- Repo layout (v2):
app/public app,admin/tooling (incl.admin/pipeline/),data/data only.- Biome enforces lint and formatting.
- DOMPurify is loaded via CDN with SRI for XSS sanitization.
Files:
docs/v2/body-dryrun.mddocs/v2/upstream-issues.mdadmin/pipeline/body/lettered.test.tsdocs/v2/body-review/00-INDEX.mddocs/v2/body-review/04-label-quarantines.mddocs/v2/body-review/03-quotes-stragglers.mddocs/v2/body-review/02-orphan-refs.mdadmin/pipeline/body/labels.test.tsdocs/v2/body-review/01-broken-sequences.mddocs/v2/sefaria-report.mdadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/source.tsadmin/pipeline/body/dry-run.test.tsdocs/v2/body-migration.mdadmin/pipeline/body/census.tsdocs/superpowers/plans/2026-07-11-entry-body-model.md.tasks.jsondocs/v2/body-census.mdadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/repairs.ts
admin/**
⚙️ CodeRabbit configuration file
admin/**: Maintainer tooling that runs on Bun (not deployed). Includes:
admin/pipeline/— data pipeline from the Sefaria source (fetch, transform, validate, emit)- Admin tool v2 (Phase 3) will live here too
consoleand sequential awaits over streams are expected here
Files:
admin/pipeline/body/lettered.test.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/source.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/census.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/repairs.ts
🧠 Learnings (1)
📚 Learning: 2026-07-05T16:14:54.518Z
Learnt from: UniquePixels
Repo: UniquePixels/jastrow PR: 25
File: admin/pipeline/fetch.ts:48-75
Timestamp: 2026-07-05T16:14:54.518Z
Learning: For maintainer-run pipeline scripts under admin/pipeline (including admin/pipeline/fetch.ts), avoid adding or recommending a whole-transfer AbortSignal.timeout() for large downloads (e.g., multi-GB dumps). A fixed end-to-end timeout can abort valid successful runs. If cancellation/robustness is needed, prefer an inter-chunk idle timeout (no progress for N seconds) with appropriate retry behavior rather than timing out the entire transfer. Until the admin tool provides UI-driven cancellation/progress, the accepted recovery path for manual reruns is ctrl-C and rerunning the script.
Applied to files:
admin/pipeline/body/lettered.test.tsadmin/pipeline/body/labels.test.tsadmin/pipeline/body/repairs.test.tsadmin/pipeline/body/source.tsadmin/pipeline/body/dry-run.test.tsadmin/pipeline/body/census.tsadmin/pipeline/body/dry-run-verify.tsadmin/pipeline/body/migrate-dry.tsadmin/pipeline/body/repairs.ts
🪛 OpenGrep (1.26.0)
admin/pipeline/body/census.ts
[ERROR] 70-70: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
🔇 Additional comments (20)
admin/pipeline/body/source.ts (1)
31-34: LGTM!admin/pipeline/body/labels.test.ts (1)
134-140: LGTM!admin/pipeline/body/lettered.test.ts (1)
10-10: LGTM!admin/pipeline/body/census.ts (1)
63-72: LGTM!Also applies to: 88-88
docs/v2/body-review/03-quotes-stragglers.md (1)
23-23: Apply the previous spelling and provenance correction.Line 23 still uses
Sefaria Devsandsupprised. UseSefaria developersandsurprised.admin/pipeline/body/dry-run-verify.ts (1)
166-166: LGTM!admin/pipeline/body/dry-run.test.ts (1)
96-96: LGTM!docs/superpowers/plans/2026-07-11-entry-body-model.md.tasks.json (1)
151-151: LGTM!admin/pipeline/body/migrate-dry.ts (1)
25-28: LGTM!Also applies to: 59-59, 132-132, 164-175, 218-218
docs/v2/body-review/04-label-quarantines.md (1)
16-16: LGTM!docs/v2/sefaria-report.md (1)
156-161: LGTM!Also applies to: 303-303
docs/v2/upstream-issues.md (1)
16-16: LGTM!admin/pipeline/body/repairs.ts (1)
627-633: LGTM!admin/pipeline/body/repairs.test.ts (1)
7-12: LGTM!docs/v2/body-census.md (1)
178-180: LGTM!docs/v2/body-dryrun.md (1)
178-178: LGTM!docs/v2/body-migration.md (1)
28-28: LGTM!docs/v2/body-review/00-INDEX.md (1)
21-27: LGTM!docs/v2/body-review/01-broken-sequences.md (1)
18-26: 🗄️ Data Integrity & IntegrationTrack the superseded structural repair as an explicit limitation.
These lines state that the no-byte-change rows require a structural split on a follow-up branch. Add the issue or branch reference and confirm that PR
#36intentionally leaves this repair out of scope. Otherwise,docs/v2/body-migration.mdcan be read as final while 34 sequence issues remain.docs/v2/body-review/02-orphan-refs.md (1)
68-68: LGTM!
| if (report.repairFailures.length > 0) { | ||
| throw new Error( | ||
| `repair drift on ${report.repairFailures.length} entr(y/ies):\n${report.repairFailures.join('\n')}`, | ||
| ); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use a valid singular or plural label.
Line 237 emits entr(y/ies) literally. This makes the aggregate error unclear. Select entry for one failure and entries for multiple failures.
Proposed change
if (report.repairFailures.length > 0) {
+ const noun = report.repairFailures.length === 1 ? 'entry' : 'entries';
throw new Error(
- `repair drift on ${report.repairFailures.length} entr(y/ies):\n${report.repairFailures.join('\n')}`,
+ `repair drift on ${report.repairFailures.length} ${noun}:\n${report.repairFailures.join('\n')}`,
);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (report.repairFailures.length > 0) { | |
| throw new Error( | |
| `repair drift on ${report.repairFailures.length} entr(y/ies):\n${report.repairFailures.join('\n')}`, | |
| ); | |
| } | |
| if (report.repairFailures.length > 0) { | |
| const noun = report.repairFailures.length === 1 ? 'entry' : 'entries'; | |
| throw new Error( | |
| `repair drift on ${report.repairFailures.length} ${noun}:\n${report.repairFailures.join('\n')}`, | |
| ); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@admin/pipeline/body/migrate-dry.ts` around lines 235 - 239, Update the error
message in the repairFailures handling block to use “entry” when there is
exactly one failure and “entries” when there are multiple failures, instead of
emitting the literal “entr(y/ies)” label.
Docstring-coverage pass over admin/pipeline (maintainer request, PR #36 follow-up): every function and functional const in the body, provenance, fetch, and lib modules now carries a JSDoc stating its contract — 193/194 documented (the remainder is a script-body constant). No behavior change: bun qa green, review regen guard verified intact. Also: migrate-dry's repair-drift error now pluralizes entry/ entries properly (CodeRabbit nit). Signed-off-by: Brian L. <brian@uniquepixels.xyz>



Summary
Lands the complete Entry Body Model (§6.0) implementation — all 17
tasks of
docs/superpowers/plans/2026-07-11-entry-body-model.md,the migration prerequisite for
migrate.ts.admin/pipeline/body/: source reader, citationdetector, gloss-head rejoin, grammar index, label normalization,
lettered a)/b)/c) splitter (incl. Task 15 italic-marker classes),
B12 form-section splitter, conservative unit segmentation — each
unit-tested against a committed fixture corpus (12 edge-class files).
lettered / form-section round-trips all 32,512/32,512; 6 label
quarantines; 0 grammar quarantines.
passes over the healed corpus — 0 label quarantines, 0 empty binyan
forms, 0 schema failures, 0 unresolved orphans after repair.
bun body:reviewpreserves themaintainer's hand-recorded 2026-08-05 decisions on regen.
docs/v2/(census, dry-run, migration,review packages) with maintainer decisions recorded.
Pre-PR review battery
bun qagreen: biome format + lint--error-on-warnings, 212 tests,tsc (
exactOptionalPropertyTypes).extract.ts --check: all fixture files match extraction.v2): 25 findings triaged; fixes in64fab47(sample-rid catch-up, repairs write-back guard, own-keyvocab lookup, tsc guard in review.ts, lint hoists, stale doc numbers).
--config auto): 3detect-non-literal-regexpwarnings —accepted; patterns derive from the closed marker vocabulary and
escapeRegExp-ed reviewed refs in an offline pipeline over trustedcommitted data.
sonar-project.properties).Review findings intentionally not applied
cite.tstrailing-unclosed-anchor early return: deliberate, pinned bytest, and measured zero occurrences corpus-wide.
02-orphan-refs.mdnote,
01-broken-sequences.mdQ00997 classification,03's Sefariaclaim wording): left untouched — they are hand-recorded decision
records; flagged for the maintainer instead.
tracker's outcome fields already record reality.
Notes
*.jsonlfiles are committed entry snapshots (hencebulk-data-ok).docs/v2/are committed.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation