docs(architecture): the map matches the code that ships - #389
Merged
Merged
Conversation
§1's map, its diagram and its four tables were written before the refactor epic split the panel, the API client and the editor, and before the screen recorder existed. Every file named here now exists, and every file that matters to the map is placed: the worker's twelve importScripts, the eleven new core/ seams, the screens that grew a subject of their own, the six api/*.js files, the shared/ files the worker and the offscreen page load, and the four injected surfaces (rec-bar, review-overlay, file-overlay and the step recorder's rec-* helpers). §1.3 gains the editor's ?test=&edit mode and loses the claim that there is no update path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ding §2.1 gains the eleven messages the table never had — OPEN_RUN, OPEN_FILE_OVERLAY, STEPREC_PULL/FLUSH and the whole SCREENREC_* family — and captureTab's reply is the four-field one the worker actually sends. §3.2's writer is core/write-status.js, not the test view, and the log it uploads is EvidenceUpload.log(). §3.2b names run-lock.js and the nine files that ask it. A new §3.6 describes the screen recording, including the debugger session its fallback route holds for a whole take. The needsReinject note goes: neither the field nor the comment it warned about exists. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
§4's manifest block was missing tabCapture, offscreen and contextMenus, and listed activeTab among the permissions whose absence costs nothing — it costs the screen recording its good capture route. §4.1 gains the bound site target and the `activate` knob. §4.3 gains the foreign-frame rescue that runs before the viewport fallback, and the height clip. §5.1 and §5.2 now list every key any realm writes: the four screenRec* ones, commentDrafts, siteTarget, openRunIntent, fileOverlay, the two handoff marks and the two dragged-control positions — each with a "Written by" that resolves to a function. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…akes §6 said v2 authenticates with the raw General token; it authenticates with a per-project key the session mints on demand, and the 401 remint and the 403 corroboration are how that key is kept honest. A new §6.0 covers the read-only tri-state (#155) the panel gates every screen on. §7 is retitled: there are two debugger sessions, and the screen recording's cast route holds one for a whole take — a screenshot taken during it shares that attach. §8's claim that a replay collects env meta at replay time was backwards: each entry carries the snapshot taken at the click. Rakes 1, 2, 6, 8 and 10 name what is there now, and §10 points at the files a change actually lands in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ht files The result-summary card has four disclosures, not three, and it IS repainted by the tester's own marking — patched, not re-read. §3.5's context packet, masking, naming, pill, outbox and polish now name the six files they live in rather than step-recorder.js and editor.js. The empty-state count is measured. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CONTEXT_WEB_TARGET, evWindowEntries and evAdoptTwin no longer exist under those names; the erase paths are SettingsErase.disconnect()/forget(). Every backticked identifier in the file now resolves against extension/, except the two the §4.2 "Gone" table exists to record. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…arry Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Twelve importScripts, not eleven; an orphaned half-sentence; the label
fit lives in core/fit.js; eleven empty-state call sites, two of them
glyph-switching; the confirm dialog's fourth caller; EVIDENCE_EVENTS
answers {off}; five core files carry no global list; eight lock callers;
the review page's trim commands; and the second Icons block no longer
contradicts the first about BOXES.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
theme is written by set(); settings-erase never writes settings; the hostHistory writers named; framesOut only on the cast route; an empty or already-parked take parks nothing; any active-instance erase leaves the handoff mark; a project switch keeps the minted keys; four jwt writers; the buffer's own names; six stack lines; seven tags and seven screens; the viewport shot's debugger fallback; DevTools blocks full-page only; runsSearch's URL-intent resets. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
docs/architecture.mdis the first thing a new contributor reads, and large parts of it described acodebase that no longer ships. This brings the whole file — §0 through §10 — back in line with
extension/as it is today: the module map, the message table, the storage tables, the API legs, thechrome.debuggersection and the rakes. All 52file:NNNreferences are replaced by a file plus thefunction, const, key or message name at that spot, and the two rotting line counts (
background.js (485 lines),run-view.js (717, …)) are gone.Method
Every sentence that states something about the code was checked against the code in this worktree
before it was allowed to stay: the file was opened, the line read, and only then was the sentence
kept, corrected or replaced. Where the issue and the code disagreed, the code won and the
disagreement is reported below. Nothing was rewritten from memory of how such extensions usually
work, and nothing was kept because it sounded right. Three mechanical sweeps close the gaps a
sentence-by-sentence pass leaves: every
`path/file.ext`in the document was resolved againstthe filesystem, every
`name()`againstextension/, and every`#element-id`against thetwo HTML documents. The document's voice, structure and opinions are untouched — it is still a map
of the present, and no correction is phrased as a changelog.
Corrections
The
chrome.debuggerclaim (§1.1, §7, rake 10)chrome.debuggeruser left"; §7 titled"one screenshot at a time, and nothing else". → There are two users.
screenrec/session.jssrecStartCast()attaches and runsPage.startScreencast, holding thesession for the whole take (up to the five-minute cap). §7 is retitled and rewritten around the
difference: how long each attach stands.
recording." → It stands for the whole of a cast recording, and that bar's own Cancel is a
chrome.debugger.onDetachthe worker reads as a Stop that keeps the file(
screenrec/session.js, theonDetachlistener).standing attach instead of taking a second one —
shootViaDebugger()awaitssrecCastOwnsReady(tabId)and neither attaches nor detaches when the answer is yes(
background.js,screenrec/session.js).the same cure first:
foreignFramesOut()/foreignFramesBack()(background.js) detach theoffending
chrome-extension://iframes, retry once, and put each one back at its own parent andnext sibling.
The update path (§1.3)
api.jshas noupdateTest)". →updateTest(id, attrs)is atextension/api.jsand is exported. It PATCHes/api/v2/{project}/tests/{id}with any subset ofthe create payload, and the editor sends exactly
{title, description, priority}— deliberatelynever
suite_id, which would MOVE the test. Two callers, bothsave()ineditor/editor.js: the?test=<uid>&editmode (a real edit screen the doc did not mention at all, opened by a pencil ineditor/view.js's header), and the retry after a create whose upload leg failed, aimed atsavedIdso a half-written Save cannot leave two tests behind.The three screen-recording storage keys (§5.2)
screenRec,screenRecFileandscreenRecTarget— and a fourth the issue did not name,screenRecReviewKey, written in the samechrome.storage.session.setcall asscreenRecFile(
screenrec/session.jssrecFinish()). It is the one-shot token by which a framedscreenrec/review.htmlproves the extension framed it and the page under test did not.uploadEvidenceLog()(§3.2, §3.4)uploadEvidenceLog()inscreens/evidence.js. →EvidenceUpload.log(record)inscreens/evidence-upload.js, with the formatting beside it asEvidenceFormat.buildTxt()inscreens/evidence-format.js. Its caller iscore/write-status.js, not a screen.Six more corrections the issue did not ask for, found by reading
writeStatus, so the env meta keys are collected at replay time,not frozen at click time." This is backwards.
writeEnvMetatakesopts.replayand usesopts.envMeta— the environment snapshotted at the click and parked with the queue entry(
core/write-status.js,screens/offline-queue.jsqueueEnqueue()). Collecting at drain time isprecisely what the code avoids: it would describe whatever tab happens to be open hours later.
Bearer". v2 authenticates with a project keythe session mints on demand (
v2Token()→GET /projects/{slug}→attributes.api-key), held inmemory per boot and never typed. Two behaviours hang off that and were missing: a 401 on a minted
key drops it, re-mints and replays once, and a 403 is corroborated by an independent read before it
is believed (
request(),projectIsReadonly()).(
readonlyGate(),core/state.js;Gates.applyReadonlyBlock(),core/gates.js). Added as §6.0.between them (
renderSummaryArtifacts(),screens/test-summary.js). And "not refreshed by thetester's own marking" is no longer true:
TestSummary.refresh(record)patchesstatus/messageinto the prefetched detail and repaints, at no request cost (
refreshResultSummary()).all|passed|failed|running|scheduled|terminated(
RUN_FILTERS,screens/runs-list.js), notall|running|passed|failed|…— and the order isload-bearing, because
Fit.filterChips()hides the rightmost first.needsReinjectfield in astepRecshape comment. Neither thefield nor the comment exists anywhere in
extension/. Removed.The module map (§1)
importScriptslisted three files; it takes twelve.background.jsowns six subjects, notthree — the file overlay, the
OPEN_RUNintent, the staged-shot sweep and the presenceregistration were all unmentioned.
<script>tags at the foot ofindex.html" — there are 73, plusshared/theme.jsin the
<head>.core/table had 7 rows for 19 files. Addednav-model,toast,gates,fit,format,status-icons,suite-tree,dialog,write-status,session-restore,open-run-intent, andcorrected
core/views.js, which no longer ownsTAB_OF_VIEW, the toast, the status lines, thedegraded banner or the two self-measuring rows.
screens/list named 11 files for 27. Rewritten around the seam the split follows: where ascreen grew a subject of its own, that subject took a file.
shared/table had 17 rows for 33 files plus the API client. Addedmarkdown,hovercard,dropdown,roving,panel-link,handoff,shot-store,step-rec-core,dbg-errors,fullpage-trim,presence-match,webm-durationand the threeannot-*files, each with therealm that actually loads it (
grep -rlper file, not inference).content/rec-bar.js,content/review-overlay.js,content/file-overlay.js, and the step recorder's five-file inject —and the note that those last two are why
web_accessible_resourcesexists at all.single-job extension pages named under it:
offscreen/recorder.html,screenrec/review.html,viewer/viewer.html.§2.1 message table — eleven messages added:
OPEN_RUN,OPEN_FILE_OVERLAY,STEPREC_PULL,STEPREC_FLUSHand the tenSCREENREC_*entries.captureTab's reply is the six-field one theworker sends (
viewportOnly,framesMoved,trimmed,heightClipped,needsGrant), andSTEPREC_STATUSis the injected pill's poll — which doubles as the orphan check — not the editor's.§4 permissions — the manifest block was three permissions short (
tabCapture,offscreen,contextMenus), andactiveTabwas listed among the absences that cost nothing. It costs the screenrecording its good capture route:
chrome.tabCapturehands over a stream only where the extensionwas invoked on that tab, which is why the debugger fallback exists and why the context-menu item and
the
Alt+Shift+Rcommand matter.§4.1 —
resolveSiteTabgained a bound target (siteTargetinstorage.session, written byrememberTab()) and anactivateoption; anokanswer may now comeviaTarget.§4.3 — the debugger failure path is no longer "reject, with one exception": it detaches foreign
frames, retries, and only then falls back to the viewport shot. The
FULLPAGE_MAX_HEIGHTclip andits
heightClippedflag were undocumented.§5 storage — every
chrome.storage.*.setunderextension/was grepped across all realms. §5.1gained
handoffDeclinedAt,stepRecIndicatorPosandscreenRecBarPos; §5.2 gained the fourscreenRec*keys,commentDrafts,siteTarget,openRunIntent,fileOverlayandhandoffOpenedAt. Existing rows were corrected:polishStepsis written byeditor/rec-session.js(not
editor.js), thesessionshape carriesrunInfoOpen, theofflineQueueentry carriesreason/envMeta/prevStatus, andeditorDraft:has atest:form as well assuite:.§9 / §10 — rake 1's temporal-dead-zone example moved files (
run-lock.jsreadingtest-view.js'sstepWriteChain, plus a second one incore/gates.js); rake 6 namessyncPanelBehavior(); rake 8 is rewritten around the fact that nothing callssanitizeHtmldirectly any more —
Md.render()inshared/markdown.jsis the one path. §10's table points at thefiles a change now lands in, including the four seams a status write crosses.
The issue vs the code
screenRec,screenRecFileandscreenRecTarget" — thereare four.
screenRecReviewKeyis written in the same call asscreenRecFileand is what stops anarbitrary page from acting on a framed review. Added.
extension/screenrec/session.jsattaches and detaches the debugger and runsPage.startScreencast" — true, but only on one of two routes.srecStart()preferschrome.tabCapture.getMediaStreamId()and falls through to the cast only when that throws, i.e.on a tab with no
activeTabgrant. The doc says so, because "the recorder holds a debuggersession" without that qualifier would send a reader looking for an attach that a granted tab never
makes.
52 were stale, not seven of seven; the file has moved on since the issue was written too. All are
replaced by names.
uploadEvidenceLog()is put inscreens/evidence.js. It moved." — confirmed, and the callermoved as well: it is reached from
core/write-status.js, so §3.2's diagram named the wrong fileon both sides of that arrow.
routes/launch.js,core/site-resume.js" —neither is a defect, and both are left in place.
core/site-resume.jsappears only in §4.2'sGone | Was table, which exists precisely to record deleted machinery; a file listed there is
supposed not to exist.
routes/launch.jsis a citation of the product's own Ember app, not ofthis repo — the sentence already said "the web's", and now says so unmistakably.
P1-10 (two debugger users) confirmed and fixed. P2-18's line-drift rows are all superseded: its
own numbers (876-line
background.js, 42 script tags,core/views.js:528-544) are themselvesstale, so none was used as a target; the lines were re-derived from the code and replaced by names.
Its
onboardingrow is already fixed in the doc, and its P1-7 egress finding is fixed in thecode —
ApiAssets.fetchAssetnow defaultsinstanceOnly: true, so §0's "single egress, noexceptions" rule stands as written and was kept. P2-7 (
envInfoOnFailruns on every status write,not only a failure) is a key-name complaint about the code, not a false claim in the doc: §5.1
lists the key, §3.2's diagram already shows
writeEnvMetarunning on every write, and only theConsole & network logkey is gated onfailed. Left alone.Second pass
Two verifiers read all 273 listed claims against the code, one per half of the document, and each half end to end for sentences the list missed: 258 confirmed outright. Their findings are folded in as two commits — in §0–§3.3, twelve
importScripts(the text said eleven), an orphaned half-sentence, the label fit's real home (Fit.actionLabels()incore/fit.js), eleven empty-state call sites of which two switch glyph, the confirm dialog's fourth caller (the offline queue),EVIDENCE_EVENTSanswering{off}, the fivecore/files with no/* global */list, eight lock callers, the review page's threetrim-*commands, and the second Icons block, which contradicted the first aboutBOXESand is now folded into it; in §3.4–§10,themewritten byset(),settings-erase.jsnever writingsettings, thehostHistorywriters named,framesOutonly on the cast route, an empty or already-parked take parking nothing, any active-instance erase leaving the handoff mark, a project switch keeping the minted v2 keys, the fourthcapabilities.jwtwriter (resetProjectScopedState()), the buffer's own names (evBuf.push(),isError), six stack lines rather than frames, seven tags betweenrun-lock.jsandtest-view.js(not fourteen), the viewport shot's debugger fallback, DevTools blocking the full-page shot only, andrunsSearchreset on the URL-intent paths too.Five tracker numbers the writer had introduced (
#14,#62,#155,#158,#160) were removed: those references in this repository's code point at a different tracker, and the document carries none it did not already have.Left alone
Testrun#add_step!,Run#calculate_counters,TestrunSerializer,RunSerializer,Api::TemplatesController#index,Test#to_url,extra-run-actions.hbs,rungroup.rb,routes/launch.js. These cannot be verified from thisworktree. Four of them are corroborated by comments in
extension/that say "verified live"; therest are kept as written, with their attribution made explicit where a reader might mistake them
for files in this repo.
decision was taken. Where such a passage carried a checkable fact (a token name, a pixel value, a
count) the fact was checked; the reasoning around it is the document's own voice and was not
restyled.
#tc-polish-btnis the one element id in the document with no match in either HTML file. It iscorrect:
editor/editor.jsbuilds that button at runtime.The issue also proposed a CI check that would validate doc references against the code. The
maintainer decided against it, so no test was written and none is included here.
Verified after the last commit:
node --test tests/*.test.mjs→ 3544 tests, 0 fail, 2 todo;git statusclean.Closes #103
🤖 Generated with Claude Code