Midshift is unusually heavily documented for a one-developer product: roughly 46,000 words of Markdown across a README, an architecture document, an API reference, a deployment guide, a security policy and a very long working-rules file (CLAUDE.md), plus source code in which about one line in five is a comment. Much of it is candid and useful β the architecture document openly lists what is missing (no error tracker, no tested backups, no review gate before production). However, the documents are written as a running decision log by and for an AI-assisted development workflow, they are dense and hard for a newcomer to navigate, and they have drifted from the code in several places, including facts that matter: how to set up a fresh database, whether a security migration has been applied, and who to contact about a vulnerability. Of 16 specific claims checked against the code, 3 are current, 3 are partly current, 9 have drifted and 1 is an unfilled placeholder. A new team could take the product over, but would need a short, correct onboarding path, an operations runbook and a data-model diagram first.
π― Rating
π‘ βββββ 3 / 5 β Adequate (Amber). Coverage is broad and the API reference is near-complete (82 of 83 route files documented), but material drift on onboarding and security facts, contradictions between documents, and the absence of runbooks and incident procedures mean the documentation cannot yet be relied on without verification.
Comment-to-code ratio 0.28 (comments are ~22% of non-blank lines)
High density; comments explain why (decision history), consistent with the stated convention
[Observed] Line counts from wc -l; comment counts from the shared cloc facts.
2. Style
Decision-log narrative. Documents record why things changed, with dates and post-mortems ("Three pushes to main sat red that way on 2026-09-06β¦", CLAUDE.md:649). This preserves reasoning well but buries current-state facts among history; e.g. the migrations section of CLAUDE.md runs to ~250 lines and lists migrations out of numeric order. [Observed]
AI-session orientation.CLAUDE.md, AGENTS.md and docs/HANDOVER.md are explicitly instructions to AI coding sessions ("For a session that picks the build up mid-stream", docs/HANDOVER.md:3), including how to publish screenshots to a claude.ai artifact board (docs/HANDOVER.md:62-93). A human team inherits a workflow built around one owner plus AI agents. [Observed]
Density. Long sentences, private vocabulary ("the door", "the strip", "the board", "the ledger", "planted"), and cross-references by section name. High cost to a newcomer. [Observed]
Candour.ARCHITECTURE.md Β§9β10 states plainly: no error tracker, no uptime probe, no SLO, no alerting, backups untested, no review gate between commit and production, no retention for logs. This is a strength for due diligence. [Observed] ARCHITECTURE.md:522-560,505-519
3. Accuracy check (16 claims sampled)
#
Claim (where)
What the code shows
Verdict
1
Branding, owner and domain "come from environment variables" (README.md:31-32)
Organisation name/logo/website are rows in settings read by src/lib/branding.ts:14-19,168; only productName comes from env (src/lib/config.ts:13); OWNER_EMAIL is still env. The README's own env table (line ~84) contradicts its earlier sentence.
Drifted (partly: owner is env)
2
"Ask β¦ with voice input" (README.md:28-29)
Web Speech API used at src/app/(app)/workspace/ask-sheet.tsx:130-131, mic button line 159
Current
3
Ask is rule-based, no model provider (README.md, ARCHITECTURE.md Β§2)
src/lib/ask-intent.ts is keyword rules; no AI SDK in package.json
supabase/baseline.sql:13-19 says 040 is in and ran in production; CLAUDE.md says applied 2026-09-06; supabase/tests/040_rls.sql and scripts/rls-check.sh exist
Drifted (also contradicts docs/NEW_DEPLOYMENT.md:88 "RUNS now" vs :200 "stays unrun")
5
Security contact (SECURITY.md:5)
security@example.com, with a note to replace it
Placeholder β no working disclosure channel
6
Fresh DB: run baseline, "then any migration numbered above 061 (the baseline is 001-061)" (README.md:70-71; docs/NEW_DEPLOYMENT.md:70-72,195)
Baseline header: "migrations 001β090 and 092 united (091 is not folded in)" (supabase/baseline.sql:2); the same header later also says "001β078" and "58 files". Following the README re-runs 062β092 on top of a schema that already contains them.
Drifted π (High β onboarding instruction)
7
docs/API.md documents "every route handler"
83 route files on disk; 82 documented. Missing: PATCH /api/campaigns/[id]/ad-units/[unitId]/cap (copywriter sets a format's character cap for every unit of that format). Documented-but-absent paths are only the retired /api/dam-references and /api/plugin/*, both correctly marked as removed.
23 route files now gate with canEditArea / canApprove (discipline-scoped), 14 with canEditCampaign. The vocabulary table has no "area/discipline" term; it is described only inside individual rows.
Partly current
9
Vercel has "One cron" (ARCHITECTURE.md:87, diagram line ~68)
vercel.json schedules two: purge-review 03:00 and overdue 07:00. .env.example:22 also says CRON_SECRET gates only purge-review.
Drifted
10
Data model: baseline "creates 40 tables" and lists them (ARCHITECTURE.md:223-235)
44 distinct create table in supabase/baseline.sql; the section's table list omits brief_versions, campaign_products, campaign_questions, media_strategy_lines, season_findings
Drifted
11
Unit tests: "26 files, 254 tests" (ARCHITECTURE.md:488)
copy-deck-parser.baseline.test.ts:14-16; no present page under src/app; next.config.ts:23-33 redirects
Current
β
Addendum from the journey run (Module 7), not part of the 16-claim sample: README lists "Ask β a rule-based assistant over the record β¦ with voice input" as a feature
e2e/journeys/chain-home-tracking.spec.ts:149,960 skips 7 tests because the Ask button is not rendered: "Ask is parked until the API exists"
Unclear β the route and logic exist (src/lib/ask-intent.ts, src/app/api/ask), but the button is not rendered in the QA build; whether it is exposed in production is [Unavailable]
Additional minor drift [Observed]: docs/README.md describes UTM_REFERENCE.md against "today's generateUtm()", which was removed (src/lib/utils.ts:10); .env.example keeps comment headers for retired season/domain variables with no variable beneath; README.md "Provenance" says the repository began 31 August 2026 and SECURITY.md says 2026-09-01, while the audited repository is a single squashed commit of 2026-10-06; ARCHITECTURE.md Β§11 correctly flags google-auth-library and date-fns as declared but unused (confirmed: no imports in src, scripts, e2e).
Tally (16 claims): current 3 (#2, #3, #16); partly current 3 (#7, #8, #15); drifted 9 (#1, #4, #6, #9, #10, #11, #12, #13, #14); placeholder 1 (#5). Drift clusters in counts and dated status statements, which the documents restate in several places without any check.
4. API documentation completeness
Aspect
Status
Tag
Route coverage
82 of 83 route files (98.8%); missing β¦/ad-units/[unitId]/cap
[Observed]
Per-route auth rule, purpose, side effects (logActivity, notifications, emails)
Present for every documented route, unusually thorough
[Observed]
Request/response shapes
Prose in table cells (e.g. docs/API.md:89 is a single several-hundred-word cell); no types, no examples, no error catalogue beyond a shared status-code paragraph
[Observed]
Machine-readable spec (OpenAPI/JSON Schema)
None
[Observed]
Versioning / stability promise
None; API is internal to the Next.js app
[Observed]
Drift control
scripts/harness-contract.js checks routes against the QA harness, not against docs/API.md; the cap route shows docs can fall behind silently
[Observed]
Freshness stamp
"read from the code on 2026-09-07" (docs/API.md:3) while later routes (085, 086 era, 2026-09-13/14) are included β the stamp itself is stale
[Observed]
5. Could a new team take over? Gaps in priority order
Priority
Missing or weak
Why it matters
1
A correct, short onboarding path (fresh database, environment, first admin, seed data)
README and NEW_DEPLOYMENT give a wrong migration instruction and contradict each other on 040
2
Operations runbook and incident procedure β no on-call, no alerting, no restore procedure, no "site down" steps
ARCHITECTURE.md Β§9 confirms none exist; SECURITY.md has no real contact
3
Environment matrix β which deployments exist, their regions, plans, which migrations each has run
Migration register lives only in CLAUDE.md prose; scripts/migrations-applied.sql exists but its results are not recorded per deployment
4
Entity-relationship diagram / data dictionary for the 44 tables (legacy and orphaned tables marked)
Only a grouped table list, already stale
5
Machine-readable API spec generated or checked against code
Prevents silent drift
6
Separation of human docs from AI-agent instructions and a current-state architecture without the decision history inline
Lowers the cost of reading; history can move to ADRs
7
Externally held knowledge brought in: product direction, data-protection posture, open-decisions "comment ledger", the claude.ai design board (docs/README.md:31-33; docs/HANDOVER.md:62-70,231-235)
Key-person and tool dependency
8
Changelog / release notes
ARCHITECTURE.md Β§8: "no version tags and no changelog beyond the migration register"
Route diff: find src/app/api -name route.ts (83) vs paths extracted from docs/API.md with grep -o '/api/[^]*'andcomm β one undocumented (/cap`), two documented-as-retired.
Path existence check over every backticked src/β¦, scripts/β¦, docs/β¦ path in the five main docs: all resolve except retired src/lib/plugin-auth.ts (correctly described as gone).
β οΈ Risks
#
Risk
Severity
Effort
D1
Wrong fresh-deployment instructions: README and NEW_DEPLOYMENT say the baseline is 001β061 and to run every later migration; the baseline already contains up to 092 (except 091). Re-running data migrations (e.g. 062, 064) on an already-seeded schema relies on each being idempotent, which is claimed but not verified for all. A new deployment could be mis-built or silently miss 091.
π High
S
D2
No working vulnerability-disclosure channel (security@example.com) and a stale statement that a security migration is unrun β misleads researchers and auditors.
π High
S
D3
No incident / operations runbook while there is also no monitoring or alerting; a new team would discover outages from users.
π High
M
D4
Documentation drift with no automated check (counts, table lists, cron count, migration status, one undocumented route); readers cannot tell which statements are current.
π‘ Medium
M
D5
Key-person and tool dependency in the docs: handover process built around one owner, AI sessions and an external claude.ai board / comment ledger; product direction held outside the repository.
π‘ Medium
M
D6
Migration register only in CLAUDE.md prose, for possibly several deployments, with contradictions (088 "not run" yet folded into baseline).
π‘ Medium
S
D7
High reading cost: dense narrative, private vocabulary and AI-agent instructions mixed with human documentation slow onboarding.
βͺ Low
M
β Recommendations
#
Recommendation
Priority
Effort
1
Correct the onboarding path in README.md and docs/NEW_DEPLOYMENT.md: baseline contents (001β090, 092), then exactly which migrations to run (091); fix the baseline header's internal contradictions; remove "040 stays unrun".
π High
S
2
Replace the placeholder security contact; update SECURITY.md scope notes to reflect 040 applied; add a security.txt.
π High
S
3
Write an operations runbook: deploy/rollback, migration procedure, backup/restore (and test one), cron failure, Resend failure, Supabase outage, who to call. Pair with minimal monitoring.
π High
M
4
Create a per-deployment environment matrix (region, plan tier, migrations applied with date, env vars set, cron secret set) outside CLAUDE.md, generated from scripts/migrations-applied.sql output.
π High
S
5
Add an ER diagram and data dictionary generated from supabase/baseline.sql, marking legacy/orphaned tables and enum values.
π‘ Medium
SβM
6
Document the /cap route; extend scripts/harness-contract.js (or a new test) to fail when a route file is absent from docs/API.md; consider generating an OpenAPI description from route validators.
π‘ Medium
M
7
Remove counts and "verified on " figures from prose docs or generate them; refresh ARCHITECTURE.md Β§2, Β§5, Β§8 and CLAUDE.md (journeys, CI, 088).
π‘ Medium
S
8
Split human-facing documentation from AI-agent instructions; move decision history into dated ADRs and keep ARCHITECTURE.md as current state only. Index all live docs in docs/README.md.
βͺ Low
M
9
Bring externally held product-direction, compliance-posture and open-decision records into the data room or repository.