youtube-transcript-to-pdf

Repo Bootstrap Audit — 2026-08-27

Audit of youtube-transcript-to-pdf against the mdb-tam repository file standard, and a record of what was applied, what was adapted, and what was deliberately excluded.

Repository shape: browser extension. No server, no datastore, no MCP surface, no operator dashboard, zero dependencies. Much of the mdb-tam standard assumes a long-running service, so this audit adapts rather than transcribes.

Working tree at audit time: clean, at cc02654.

Applied

Workflow infrastructure

File Status Notes
CLAUDE.md Created Commands, layout, seven binding rules, verification expectations.
AGENTS.md Created No repo-local agents exist; documents the external agents that operate here and the conventions binding automated edits.
GEMINI.md Created Short form of CLAUDE.md.
.github/copilot-instructions.md Created Opens with ## Default Execution Strategy as the standard requires.

Dotfile meta

File Status
.editorconfig Created
.gitattributes Created — LF normalisation, binary markers, generated-file marks
.nvmrc Created — Node 22
.vscode/settings.json, extensions.json, launch.json Created
.github/workflows/ci.yml Created — checks on Node 20/22/24, then packaging
.github/dependabot.yml Created — GitHub Actions only
.github/CODEOWNERS Created
.github/PULL_REQUEST_TEMPLATE.md Created
.github/ISSUE_TEMPLATE/bug_report.md, feature_request.md Created
.github/SECURITY.md Created
CONTRIBUTING.md, CODE_OF_CONDUCT.md Created
.gitignore, LICENSE Already present

Documentation suite

ARCHITECTURE.md, DEVELOPMENT.md, COMPONENTS.md, SECURITY.md, TESTING.md, INSTALLATION.md, requirements.md, logging.md, caching-and-optimization.md, external-calls.md, integrations-and-assumptions.md, known-issues.md, onboarding.md, codebase-overview.md — all created. README.md already existed and was left as the project’s entry point.

Reference and index

File Status Notes
docs/codebase-overview.md Created Covers every directory in the repository.
docs/high_signal_file_index.json Created 19 entries, generated from the tree so it cannot be invented.
scripts/check-doc-indexes.mjs Created Validates every indexed path, flags source files missing from the index, --prune drops dead entries. Wired into CI as npm run lint:docs.

Runbooks

docs/runbooks/transcript-panel-broke.md and docs/runbooks/release.md — the two recurring operational procedures this project actually has.

Excluded, with reasons

Each of these is a real part of the mdb-tam standard that does not map onto a browser extension. Recorded here so a future audit does not re-raise them.

Standard item Why not
server/src/lib/operations-registry.js and the generated docs/operations-registry.json The registry exists to make a service’s many external calls introspectable and runnable. This extension has three external calls, all in one file, fully documented in external-calls.md. A registry would be indirection over a table with three rows.
docs/tool-inventory.json Inventories a server’s HTTP routes. There is no server and there are no routes.
scripts/generate-ops-registry-doc.mjs, ops:doc / ops:doc:check Generates and drift-checks the registry doc above, which does not exist.
The five-standard auto-remediation contract (CLI trigger, centralised error log, auto-remediation map, dashboard card, datastore verification) Presupposes a service with an operator dashboard and a datastore. The applicable parts — per-call error handling, logging, and documentation — are satisfied and recorded in external-calls.md. There is nothing to remediate into and nothing to verify against.
docs/MCP.md, .mcp.json, .vscode/mcp.json The project exposes and consumes no MCP servers.
scripts/semantic_indexer.py, scripts/watch_and_index.sh A local Ollama and ChromaDB embedding pipeline. This is TAM-internal retrieval infrastructure, not something a public extension repo should carry.
memory.md, prompts.md, scripts/rotate-workflow-logs.mjs, docs/archive/ Append-forever operator logs recording every session request. That convention suits an internal working repo; committing session transcripts into an extension repository is noise for contributors and a privacy footprint for the maintainer.
.env.example The extension reads no configuration. grep -rn "process.env" src/ returns nothing outside scripts/, which reads none either.
.tool-versions .nvmrc already pins the only toolchain.
CHROMEWEBSTORE.md No longer excluded. Created later the same day along with PRIVACY.md, the store screenshots, and the two asset-generation scripts. See the addendum below.

Findings from the audit itself

Severity Finding Resolution
Medium README.md cited a test count that had drifted from the suite. Corrected; runbooks/release.md now includes a grep step for count drift.
Medium No CI. Every check was manual. ci.yml runs manifest validation, tests, and doc index validation on three Node versions, then packages.
Medium Nothing prevented documentation index rot. check-doc-indexes.mjs, gated in CI. It caught its own first drift during this run.
Low package.json carried no repository, bugs, or homepage fields. Added.

Verification

npm run lint:manifest   manifest.json OK — YouTube Transcript to PDF v1.0.0
npm test                31 tests, 31 pass, 0 fail
npm run lint:docs       19 entries, all paths resolve
npm run build           dist/youtube-transcript-to-pdf-1.0.0.zip

Next audit

Re-run after any change to manifest.json permissions, any YouTube markup migration, or before a first Chrome Web Store submission.

Addendum — Chrome Web Store preparation (same day)

Added after the audit above, when the decision was made to prepare a store submission:

File Purpose
CHROMEWEBSTORE.md Listing copy, per-permission justifications, data-use disclosure, asset inventory, and the blockers that must clear before submission.
PRIVACY.md Privacy policy. Published via GitHub Pages and verified live at https://mithudso.github.io/youtube-transcript-to-pdf/PRIVACY.html.
scripts/build-store-assets.mjs Renders the extension’s real popup and viewer markup into screenshot harness pages and generates a genuine PDF through the shipping writer.
scripts/compose-store-screenshots.py Composes the captured renders into three 1280×800 screenshots and a 440×280 promo tile.
store-assets/ The generated graphics and their inputs. Excluded from the packaged archive.

Two submission risks were identified, raised rather than silently shipped, and then resolved: the icon closely evoked YouTube’s play-button mark, and the extension name led with a trademark.

The repository was also made public, and three Dependabot pull requests bumping GitHub Actions to v7 were merged.

Resolution — store submission blockers

Blocker Resolution
Icon read as YouTube’s play button Redrawn as a document — a page with a turned-down corner and lines of text — by scripts/generate-icons.py. Text lines are dropped below 32px, where they would blur into a smear.
Name led with a trademark Renamed “YouTube Transcript to PDF” → “Transcript to PDF for YouTube” across manifest.json, CHROMEWEBSTORE.md, README.md, PRIVACY.md, docs/INSTALLATION.md, and the PDF Producer string.
Publisher name and contact email unset Set in CHROMEWEBSTORE.md.
Screenshot 1 was a harness render Still open — browser automation cannot reach chrome-extension:// URLs, so a live popup capture must be taken by hand. Recorded in runbooks/release.md.

The archive name was also decoupled from the display name: package-extension.mjs now derives it from package.json, so renaming the extension no longer changes the release artifact every document refers to.

The verification line above records the pre-rename name, which is what ran at the time of the audit.