Repository Analysis

nyblnet/bento

Bento, the office suite that fits in a file

5.8 Low AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of nyblnet/bento, a TypeScript project with 4,576 GitHub stars. SynthScan v2.0 examined 208,189 lines of code across 494 source files, recording 799 pattern matches distributed across 6 syntactic categories. The overall adjusted score of 5.8 places this repository in the Low AI signal band.

The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).

5.8
Adjusted Score
5.8
Raw Score
100%
Time Factor
2026-08-29
Last Push
4.6K
Stars
TypeScript
Language
208.2K
Lines of Code
494
Files
799
Pattern Hits
2026-08-29
Scan Date
0.01
HC Hit Rate

What These Metrics Mean

Adjusted Score
Primary synthetic code indicator. Raw score normalised per 1,000 lines of code and multiplied by the temporal discount factor. This is the definitive comparative metric — use it to rank repositories by AI authorship density.
Raw Score
The unmodified sum of all severity-weighted, context-multiplied pattern match scores before temporal discounting. Reflects the absolute signal strength independent of when the repository was last active.
Time Factor
The temporal discount multiplier (0–100%) applied to the raw score. Repositories last updated before ChatGPT's launch (Nov 2022) receive a 5% factor. Full signal is only assigned to repositories active in the post-adoption era (Jan 2024+).
Pattern Hits
Total count of individual pattern matches across all files and categories. A high hit count with a low score may indicate a very large codebase with isolated AI snippets; a low count with a high score indicates dense, concentrated AI signatures.
HC Hit Rate
High+Critical pattern hits per file, averaged across the repository. This orthogonal signal catches repositories where a few files are densely packed with high-severity AI tells — a strong indicator even when the normalised score appears moderate due to codebase size.
Lines of Code / Files
Total lines and files analysed. The scanner examines 94 file extensions. These denominators are used to normalise the score, enabling fair comparison between repositories of vastly different sizes.

Score History

Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.

No multi-scan history yet — run the scanner again to build trend data.

Severity Breakdown

Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.

CRITICAL 0HIGH 6MEDIUM 185LOW 608

Directory Score Breakdown

This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.

Pattern Findings

The scanner identified 799 distinct pattern matches across 6 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.

Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.

Over-Commented Block601 hits · 594 pts
SeverityFileLineSnippetContext
LOWhome/bridge.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/bridge.js21// the transport — it is the FileSystemWritableFileStream semantics below, whoseCOMMENT
LOWhome/bridge.js81 const want = (opts && opts.suggestedName) || ''COMMENT
LOWhome/webext/src/route.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/page-bridge.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/page-bridge.js201 // nothing to resolve until the write itself. The extension validates theCOMMENT
LOWhome/webext/src/background.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/background.js21// machine. So every message re-resolves from the grant; nothing is cached.COMMENT
LOWhome/webext/src/background.js141 // the sender's file, and treating it as such destroys documents:COMMENT
LOWhome/webext/src/db.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/db.js21// cache derived, disposable: one entry per document, holding what was readCOMMENT
LOWhome/webext/src/update.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/theme.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/library.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/library.js181 const head = await file.slice(0, HEAD_BYTES).text()COMMENT
LOWhome/webext/src/library.js421 const net = deps.fetch ?? fetchCOMMENT
LOWhome/webext/src/home.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/home.js681 if (upd?.version) {COMMENT
LOWhome/webext/src/home.js941 closeMenu()COMMENT
LOWhome/webext/src/release.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/release.js21// party that serves the bytes.COMMENT
LOWhome/webext/src/release.js61// The 359-byte difference is a Cloudflare Web Analytics beacon the edge injectsCOMMENT
LOWhome/webext/src/relay.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/i18n.js1// SPDX-License-Identifier: MITCOMMENT
LOWhome/webext/src/i18n.js21//COMMENT
LOWhome/ios/SearchViewController.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/BentoDocument.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/Releases.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/Releases.swift21/// THIS IS THE ONE THING THE HOST FETCHES. The app makes no other networkCOMMENT
LOWhome/ios/Releases.swift101 guard let url = payload["url"] as? String, !url.isEmpty else {COMMENT
LOWhome/ios/Releases.swift181 throw Failed(message: "the downloaded app did not match its signed hash — refusing it")COMMENT
LOWhome/ios/Releases.swift201 /// signatures as RAW `r || s` — 64 bytes, two fixed-width integers.COMMENT
LOWhome/ios/Releases.swift261 // Accept: text/html,…,*/*;q=0.8 689,675 bytes — does NOTCOMMENT
LOWhome/ios/FolderGrants.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/project.yml21 buildPhase: resourcesCOMMENT
LOWhome/ios/project.yml41 # committed. Unset, it expands to empty and simulator builds areCOMMENT
LOWhome/ios/BentoIndex.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/BentoIndex.swift21/// moment a document contains an emoji or a CJK character — which is to say, onCOMMENT
LOWhome/ios/BentoIndex.swift41 /// Bento document — the `.bento.html` name is a convention, and conventionsCOMMENT
LOWhome/ios/BentoIndex.swift61 // MARK: - ResultCOMMENT
LOWhome/ios/BentoIndex.swift101 /// first `sniffBytes`, `head` the first `headBytes`, `whole` all of it (orCOMMENT
LOWhome/ios/BentoIndex.swift221 guard let start = whole.firstIndex(ofSequence: Array("<div data-bento-preview".utf16)) else { return nil }COMMENT
LOWhome/ios/BentoIndex.swift241COMMENT
LOWhome/ios/LibraryIndex.swift21}COMMENT
LOWhome/ios/EditorViewController.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/EditorViewController.swift21/// The host is PER DOCUMENT, derived from the file's own path, not a singleCOMMENT
LOWhome/ios/EditorViewController.swift61 /// Called when the user leaves the document. The browser owns teardown —COMMENT
LOWhome/ios/EditorViewController.swift101 /// Necessary because on iPhone there is no longer a fullscreen signal to keyCOMMENT
LOWhome/ios/EditorViewController.swift121 /// landscape, but the bar was no more justified there; it was only ever aCOMMENT
LOWhome/ios/EditorViewController.swift141 ///COMMENT
LOWhome/ios/EditorViewController.swift181 view.setNeedsLayout()COMMENT
LOWhome/ios/EditorViewController.swift241 // letterbox onto the slide. It does not even hide the status bar onCOMMENT
LOWhome/ios/EditorViewController.swift381 let a = UIAlertController(title: nil, message: message, preferredStyle: .alert)COMMENT
LOWhome/ios/EditorViewController.swift501 /// credentials: a read-only copy has the owner keys stripped), and it is notCOMMENT
LOWhome/ios/EditorViewController.swift521 /// the file on disk. Routing on `openDocumentVended` alone could not work:COMMENT
LOWhome/ios/EditorViewController.swift541 /// raw the JS parser CONSUMES that escape — the page gets back a documentCOMMENT
LOWhome/ios/EditorViewController.swift561 /// Reduce a page-supplied filename to ONE plain component, or refuse it.COMMENT
LOWhome/ios/Brand.swift1// SPDX-License-Identifier: MITCOMMENT
LOWhome/ios/DocumentBrowserViewController.swift41 func openIndexed(_ url: URL) { openEditor(url) }COMMENT
LOW…/android/app/src/main/java/page/bento/home/Releases.kt161 // field is missing and `want` is never null, so the comparison alreadyCOMMENT
541 more matches not shown…
Decorative Section Separators181 hits · 548 pts
SeverityFileLineSnippetContext
MEDIUMslides/src/starterdeck.ts345 // ── 1 · TITLE ──────────────────────────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts437 // ── 2 · ONE FILE ───────────────────────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts482 // ── 3 · NO MOVING PARTS (staggers + count-ups, arriving by morph) ─────COMMENT
MEDIUMslides/src/starterdeck.ts525 // ── 4 · MORPH MANIFESTO ────────────────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts759 // ── 6 · CHARTS ALIVE (+ hidden pie state) ──────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts870 // ── 7 · TABLES (real HTML table) ───────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts956 // ── 8 · MOMENTUM (line-chart hero) ─────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts983 // ── 9 · MOTION & LINES ─────────────────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts1028 // ── 10 · CHOREOGRAPHY (base + two hidden states) ──────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts1118 // ── 11 · HOVER FOCUS ───────────────────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts1168 // ── 12 · MARKDOWN ──────────────────────────────────────────────────────COMMENT
MEDIUMslides/src/starterdeck.ts1201 // ── 13 · CLOSE ─────────────────────────────────────────────────────────COMMENT
MEDIUMtype/src/inline.ts307// ─────────────────────────────────────────────────────────── model → HTMLCOMMENT
MEDIUMtype/src/inline.ts484// ─────────────────────────────────────────────────────────── HTML → modelCOMMENT
MEDIUMtype/src/comments.ts12// ─────────────────────────────────────────────────────────── the four choicesCOMMENT
MEDIUMtype/src/comments.ts40// ─────────────────────────────────────────────── how comments stay out of printCOMMENT
MEDIUMtype/src/comments.ts54// ───────────────────────────────────────────────────────── NEEDS FROM THE CORECOMMENT
MEDIUMtype/src/comments.ts145// ───────────────────────────────────────────────────────────────── the shapeCOMMENT
MEDIUMtype/src/comments.ts222// ─────────────────────────────────────────────────── reading and writing themCOMMENT
MEDIUMtype/src/comments.ts297// ───────────────────────────────────────────────────────── anchor maintenanceCOMMENT
MEDIUMtype/src/comments.ts436// ───────────────────────────────────────────────────────────── thread logicCOMMENT
MEDIUMtype/src/comments.ts526// ────────────────────────────────────── the hooks the core calls (see (B))COMMENT
MEDIUMtype/src/comments.ts561// ═══════════════════════════════════════════════════════════════════════ UICOMMENT
MEDIUMtype/src/comments.ts931// ─────────────────────────────────────────────────────────────── the featureCOMMENT
MEDIUMtype/src/comments.ts1072// ─────────────────────────────────────────────────────── showing and hidingCOMMENT
MEDIUMtype/src/docstyles.ts52// ═══════════════════════════════════════════════════════════ resolution (pure)COMMENT
MEDIUMtype/src/docstyles.ts298// ═══════════════════════════════════════════════════════════════════ the UICOMMENT
MEDIUMtype/src/main.ts46// ───────────────────────────────────────────────────────────── the documentCOMMENT
MEDIUMtype/src/main.ts96// ───────────────────────────────────────────────────────────────── chromeCOMMENT
MEDIUMtype/src/main.ts179// ───────────────────────────────────────────────────── chrome: labels & iconsCOMMENT
MEDIUMtype/src/main.ts281// ─────────────────────────────────────────────── the feature registry, renderedCOMMENT
MEDIUMtype/src/main.ts681// ────────────────────────────────────────────────────────── sidebarCOMMENT
MEDIUMtype/src/main.ts764// ───────────────────────────────────────────── revisions and redliningCOMMENT
MEDIUMtype/src/main.ts856// ─────────────────────────────────────────────────────────── signaturesCOMMENT
MEDIUMtype/src/main.ts955// ─────────────────────────────────────────────────────────── a small toastCOMMENT
MEDIUMtype/src/main.ts971// ─────────────────────────────────────────────────────────────── savingCOMMENT
MEDIUMtype/src/main.ts1020// ─────────────────────────────────────────────────────────────── printingCOMMENT
MEDIUMtype/src/main.ts1098// ─────────────────────────────────────────────────────────────────── readyCOMMENT
MEDIUMtype/src/editor.ts55 // ───────────────────────────────────────────────────────── caret ↔ modelCOMMENT
MEDIUMtype/src/editor.ts140 // ─────────────────────────────────────────────────────────── inputCOMMENT
MEDIUMtype/src/editor.ts276 // ────────────────────────────────────────────────────────── formattingCOMMENT
MEDIUMtype/src/editor.ts483 // ───────────────────────────────────────────────────────────── keysCOMMENT
MEDIUMtype/src/props.ts38// ─────────────────────────────────────────────────────────────── small partsCOMMENT
MEDIUMtype/src/props.ts109// ────────────────────────────────────────────────────────────────── sectionsCOMMENT
MEDIUMtype/src/props.ts464// ──────────────────────────────────────────────────────────────── the panelCOMMENT
MEDIUMtype/src/math.ts4// ─────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMtype/src/math.ts6// ─────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMtype/src/math.ts15// ═══ WHAT IS SUPPORTED ══════════════════════════════════════════════════════COMMENT
MEDIUMtype/src/math.ts42// ═══ WHAT IS NOT ════════════════════════════════════════════════════════════COMMENT
MEDIUMtype/src/math.ts65// ═══ HOW MATH FITS THE MODEL, AND WHY ═══════════════════════════════════════COMMENT
MEDIUMtype/src/math.ts126// ═══ NEEDS FROM THE CORE ════════════════════════════════════════════════════COMMENT
MEDIUMtype/src/math.ts239// ───────────────────────────────────────────────────────────── the renderersCOMMENT
MEDIUMtype/src/math.ts277// ───────────────────────────────────────────────────────────── editingCOMMENT
MEDIUMtype/src/math.ts365// ───────────────────────────────────────────────────────────── the chromeCOMMENT
MEDIUMtype/src/find.ts53// ───────────────────────────────────────────────────────────── the searchCOMMENT
MEDIUMtype/src/find.ts178// ─────────────────────────────────────────────────────────── decorationCOMMENT
MEDIUMtype/src/find.ts224// ────────────────────────────────────────────────────────────── the panelCOMMENT
MEDIUMtype/src/find.ts252 // ─────────────────────────────────────────────────────────── chromeCOMMENT
MEDIUMtype/src/find.ts329 // ───────────────────────────────────────────────────────── searchingCOMMENT
MEDIUMtype/src/find.ts372 // ─────────────────────────────────────────────────────── highlightingCOMMENT
121 more matches not shown…
Cross-Language Confusion (JS/TS)6 hits · 40 pts
SeverityFileLineSnippetContext
HIGHspaces/src/editor.ts5067 print()CODE
HIGHscripts/test-spaces-model.ts1288 ['py', 'def f():\n return None', 'def', 'k'],CODE
HIGHscripts/test-tray-bridge.ts142 print("ok " + b64(out) + " " + (inside ? "1" : "0"))CODE
HIGHscripts/test-tray-bridge.ts145 print("ok " + b64(exportName(arg(2))))CODE
HIGHscripts/test-tray-bridge.ts149 print("ok " + b64(targetsOpenDocument(arg(2)) ? "1" : "0"))CODE
HIGHscripts/test-tray-bridge.ts151 print("ok " + b64(jsString(arg(1))))CODE
Modern AI Meta-Vocabulary3 hits · 9 pts
SeverityFileLineSnippetContext
MEDIUMdocs/agents.md397## Layout guardrailsCOMMENT
MEDIUMscripts/test-autosave.ts18// writing into bento/slides' database since its scaffold landed.COMMENT
MEDIUMscripts/test-spaces-model.ts12// space" for a document it could not read. The scaffold did — it returnedCOMMENT
Fake / Example Data7 hits · 7 pts
SeverityFileLineSnippetContext
LOWhome/android/app/src/main/res/values-night/colors.xml19 <color name="placeholder">#24313F</color>CODE
LOWhome/android/app/src/main/res/values/colors.xml19 <color name="placeholder">#E4E9EF</color>CODE
LOWslides/src/modelkeys.generated.ts17 "text": ["align", "backdropFilter", "blend", "blur", "color", "colorGradient", "fontFamily", "fontSize", "fontWeigCODE
LOWscripts/test-spaces-undo.ts64 html: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod 'CODE
LOWscripts/test-spaces-undo.ts64 html: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod 'CODE
LOWscripts/test-type-link.ts253 const long = 'lorem ipsum dolor sit amet '.repeat(4000) + 'x';CODE
LOWscripts/test-type-link.ts253 const long = 'lorem ipsum dolor sit amet '.repeat(4000) + 'x';CODE
Self-Referential Comments1 hit · 3 pts
SeverityFileLineSnippetContext
MEDIUM.github/workflows/ci.yml467 # Creating a document downloads an app shell and writes it to the user'sCOMMENT