[{"data":1,"prerenderedAt":3907},["ShallowReactive",2],{"cycle-doc-design-c125-mcp-guide-plan.md":3},{"cycle":4,"project":7,"path":10,"title":11,"toc":12,"ast":20},{"id":5,"title":6},"c125","Operations Wizard",{"id":8,"label":9},"design","Design","mcp-guide-plan.md","The MCP tour guide: plan and test ladder",[13,14,15,16,17,18,19],"What's already in place","The answer to OQ1, in two steps","Testing it before the actual app","Order of work (once the tour files are quiet)","Built (2026-10-29, the same day)","The unscripted guide (written up 2026-10-29, not built)","Open",{"type":21,"children":22},"root",[23,68,93,104,110,259,264,277,289,448,453,459,670,676,758,763,783,1097,1102,1160,1165,1170,1384,1392,1505,1523,1531,1606,1614,1627,1635,1640,1658,1668,1674,1765,1771,1872,1878,2111,2136,2142,2226,2232,2237,2434,2440,2537,2553,2559,2578,2882,2903,2984,2992,3096,3103,3193,3202,3209,3217,3225,3231,3262,3270,3563,3573,3606,3625,3693,3701,3732,3737,3902],{"type":24,"tag":25,"props":26,"children":27},"element","p",{},[28,31,38,40,46,48,53,55,66],{"type":29,"value":30},"text","Thread ",{"type":24,"tag":32,"props":33,"children":35},"code",{"className":34},[],[36],{"type":29,"value":37},"mcp-guide",{"type":29,"value":39}," (2026-10-29), raised from c123's session: ",{"type":24,"tag":41,"props":42,"children":43},"em",{},[44],{"type":29,"value":45},"\"Can we make these tours drivable via mcp by user agent?\"",{"type":29,"value":47},", then ",{"type":24,"tag":41,"props":49,"children":50},{},[51],{"type":29,"value":52},"\"let's write it up first. Let's also consider how we can test it before trying to place it in the actual app.\"",{"type":29,"value":54}," Prompt verbatim: ",{"type":24,"tag":56,"props":57,"children":59},"a",{"href":58},"\u002Fcycles\u002Fdesign\u002Fc125\u002Fdoc\u002Fmcp-guide-prompt",[60],{"type":24,"tag":32,"props":61,"children":63},{"className":62},[],[64],{"type":29,"value":65},"mcp-guide-prompt.md",{"type":29,"value":67},".",{"type":24,"tag":25,"props":69,"children":70},{},[71,73,83,85,91],{"type":29,"value":72},"This is objective 7 and Phase 4, and it answers open question 1 (how a harness drives the page on screen). Nothing is built yet. The plan builds on the lab's tour layer (",{"type":24,"tag":56,"props":74,"children":76},{"href":75},"\u002Fcycles\u002Fdesign\u002Fc125\u002Fdoc\u002Ftour-layer",[77],{"type":24,"tag":32,"props":78,"children":80},{"className":79},[],[81],{"type":29,"value":82},"tour-layer.md",{"type":29,"value":84},"). The panel-iterations thread is editing that layer today (",{"type":24,"tag":32,"props":86,"children":88},{"className":87},[],[89],{"type":29,"value":90},"tour-panel-iterations-prompt.md",{"type":29,"value":92},"), so building waits until its files are quiet.",{"type":24,"tag":25,"props":94,"children":95},{},[96,102],{"type":24,"tag":97,"props":98,"children":99},"strong",{},[100],{"type":29,"value":101},"User agent",{"type":29,"value":103}," here means the person's own AI harness (Claude Code, Cursor, Claude Desktop). The person has the dashboard open, their agent connects to Qpoint over MCP, and the agent walks them through a tour on the screen they're already looking at.",{"type":24,"tag":105,"props":106,"children":108},"h2",{"id":107},"whats-already-in-place",[109],{"type":29,"value":13},{"type":24,"tag":111,"props":112,"children":113},"ul",{},[114,199,217],{"type":24,"tag":115,"props":116,"children":117},"li",{},[118,123,125,131,133,139,141,147,149,155,156,162,163,169,170,176,177,183,184,190,192,197],{"type":24,"tag":97,"props":119,"children":120},{},[121],{"type":29,"value":122},"One seam for tour state.",{"type":29,"value":124}," Everything goes through ",{"type":24,"tag":32,"props":126,"children":128},{"className":127},[],[129],{"type":29,"value":130},"useTour()",{"type":29,"value":132}," (",{"type":24,"tag":32,"props":134,"children":136},{"className":135},[],[137],{"type":29,"value":138},"composables\u002FuseTour.ts",{"type":29,"value":140},"): ",{"type":24,"tag":32,"props":142,"children":144},{"className":143},[],[145],{"type":29,"value":146},"start",{"type":29,"value":148},", ",{"type":24,"tag":32,"props":150,"children":152},{"className":151},[],[153],{"type":29,"value":154},"goTo",{"type":29,"value":148},{"type":24,"tag":32,"props":157,"children":159},{"className":158},[],[160],{"type":29,"value":161},"exit",{"type":29,"value":148},{"type":24,"tag":32,"props":164,"children":166},{"className":165},[],[167],{"type":29,"value":168},"setLayout",{"type":29,"value":148},{"type":24,"tag":32,"props":171,"children":173},{"className":172},[],[174],{"type":29,"value":175},"setFocus",{"type":29,"value":148},{"type":24,"tag":32,"props":178,"children":180},{"className":179},[],[181],{"type":29,"value":182},"setVariant",{"type":29,"value":148},{"type":24,"tag":32,"props":185,"children":187},{"className":186},[],[188],{"type":29,"value":189},"setMinimized",{"type":29,"value":191},". The mock bar's beats already drive the host from outside through ",{"type":24,"tag":32,"props":193,"children":195},{"className":194},[],[196],{"type":29,"value":154},{"type":29,"value":198},". A remote driver is one more caller.",{"type":24,"tag":115,"props":200,"children":201},{},[202,207,209,215],{"type":24,"tag":97,"props":203,"children":204},{},[205],{"type":29,"value":206},"Targets are IDs.",{"type":29,"value":208}," An agent points at the same ",{"type":24,"tag":32,"props":210,"children":212},{"className":211},[],[213],{"type":29,"value":214},"data-qp-id",{"type":29,"value":216}," regions the tour does. The dashboard learns nothing new.",{"type":24,"tag":115,"props":218,"children":219},{},[220,225,227,233,235,241,243,249,251,257],{"type":24,"tag":97,"props":221,"children":222},{},[223],{"type":29,"value":224},"Content is data, with a catch.",{"type":29,"value":226}," ",{"type":24,"tag":32,"props":228,"children":230},{"className":229},[],[231],{"type":29,"value":232},"data\u002Ftours\u002Fowasp-agentic.ts",{"type":29,"value":234}," imports ",{"type":24,"tag":32,"props":236,"children":238},{"className":237},[],[239],{"type":29,"value":240},"#components",{"type":29,"value":242}," and ",{"type":24,"tag":32,"props":244,"children":246},{"className":245},[],[247],{"type":29,"value":248},"#imports",{"type":29,"value":250}," for its Examples' ",{"type":24,"tag":32,"props":252,"children":254},{"className":253},[],[255],{"type":29,"value":256},"render()",{"type":29,"value":258},", and its numbers and \"what happens today\" are functions of the adapter's context. So today the text can't be read outside the running app. That's why the open tab reports it (step 2 below). Splitting each tour into text (plain data) and Examples (render functions) would let a server read it alone. It's worth doing when W3 decides Examples' final form.",{"type":24,"tag":105,"props":260,"children":262},{"id":261},"the-answer-to-oq1-in-two-steps",[263],{"type":29,"value":14},{"type":24,"tag":265,"props":266,"children":268},"h3",{"id":267},"step-1-a-page-api-windowqptour",[269,271],{"type":29,"value":270},"Step 1: a page API, ",{"type":24,"tag":32,"props":272,"children":274},{"className":273},[],[275],{"type":29,"value":276},"window.qpTour",{"type":24,"tag":25,"props":278,"children":279},{},[280,282,287],{"type":29,"value":281},"A thin, client-only plugin over ",{"type":24,"tag":32,"props":283,"children":285},{"className":284},[],[286],{"type":29,"value":130},{"type":29,"value":288},":",{"type":24,"tag":290,"props":291,"children":292},"table",{},[293,312],{"type":24,"tag":294,"props":295,"children":296},"thead",{},[297],{"type":24,"tag":298,"props":299,"children":300},"tr",{},[301,307],{"type":24,"tag":302,"props":303,"children":304},"th",{},[305],{"type":29,"value":306},"Call",{"type":24,"tag":302,"props":308,"children":309},{},[310],{"type":29,"value":311},"Does",{"type":24,"tag":313,"props":314,"children":315},"tbody",{},[316,334,351,397,414,431],{"type":24,"tag":298,"props":317,"children":318},{},[319,329],{"type":24,"tag":320,"props":321,"children":322},"td",{},[323],{"type":24,"tag":32,"props":324,"children":326},{"className":325},[],[327],{"type":29,"value":328},"tours()",{"type":24,"tag":320,"props":330,"children":331},{},[332],{"type":29,"value":333},"Each tour's id, title, stops and steps (ids, routes, beats)",{"type":24,"tag":298,"props":335,"children":336},{},[337,346],{"type":24,"tag":320,"props":338,"children":339},{},[340],{"type":24,"tag":32,"props":341,"children":343},{"className":342},[],[344],{"type":29,"value":345},"read(stepId?)",{"type":24,"tag":320,"props":347,"children":348},{},[349],{"type":29,"value":350},"A step as text: the blocks with ctx-derived numbers worked out, its targets, its action (named, not run)",{"type":24,"tag":298,"props":352,"children":353},{},[354,392],{"type":24,"tag":320,"props":355,"children":356},{},[357,363,365,371,372,378,379,385,386],{"type":24,"tag":32,"props":358,"children":360},{"className":359},[],[361],{"type":29,"value":362},"start(tourId, stepId?, view?)",{"type":29,"value":364}," \u002F ",{"type":24,"tag":32,"props":366,"children":368},{"className":367},[],[369],{"type":29,"value":370},"go(stepId)",{"type":29,"value":364},{"type":24,"tag":32,"props":373,"children":375},{"className":374},[],[376],{"type":29,"value":377},"next()",{"type":29,"value":364},{"type":24,"tag":32,"props":380,"children":382},{"className":381},[],[383],{"type":29,"value":384},"back()",{"type":29,"value":364},{"type":24,"tag":32,"props":387,"children":389},{"className":388},[],[390],{"type":29,"value":391},"end()",{"type":24,"tag":320,"props":393,"children":394},{},[395],{"type":29,"value":396},"As the panel's own controls. Routing and the glide stay the host's",{"type":24,"tag":298,"props":398,"children":399},{},[400,409],{"type":24,"tag":320,"props":401,"children":402},{},[403],{"type":24,"tag":32,"props":404,"children":406},{"className":405},[],[407],{"type":29,"value":408},"view({ layout, focus, variant, minimized })",{"type":24,"tag":320,"props":410,"children":411},{},[412],{"type":29,"value":413},"The switches the panel and mock bar already have",{"type":24,"tag":298,"props":415,"children":416},{},[417,426],{"type":24,"tag":320,"props":418,"children":419},{},[420],{"type":24,"tag":32,"props":421,"children":423},{"className":422},[],[424],{"type":29,"value":425},"highlight(id, keys?)",{"type":24,"tag":320,"props":427,"children":428},{},[429],{"type":29,"value":430},"Rings one region that no step names, for an agent's ad-hoc \"this one here\". Cleared on the next move",{"type":24,"tag":298,"props":432,"children":433},{},[434,443],{"type":24,"tag":320,"props":435,"children":436},{},[437],{"type":24,"tag":32,"props":438,"children":440},{"className":439},[],[441],{"type":29,"value":442},"state()",{"type":24,"tag":320,"props":444,"children":445},{},[446],{"type":29,"value":447},"Tour, step, page, view, and which of the step's targets are actually on the page",{"type":24,"tag":25,"props":449,"children":450},{},[451],{"type":29,"value":452},"Any agent that already controls a browser (Claude in Chrome, Claude's built-in browser, Playwright) can drive tours with this. It works on the static deploy too, where there's no server. It's also the surface step 2 calls, so there's one way in.",{"type":24,"tag":265,"props":454,"children":456},{"id":455},"step-2-the-dashboard-hosts-the-mcp-endpoint",[457],{"type":29,"value":458},"Step 2: the dashboard hosts the MCP endpoint",{"type":24,"tag":111,"props":460,"children":461},{},[462,504,543,637,654],{"type":24,"tag":115,"props":463,"children":464},{},[465,470,472,478,480,486,488,494,496,502],{"type":24,"tag":97,"props":466,"children":467},{},[468],{"type":29,"value":469},"Endpoint.",{"type":29,"value":471}," A Nitro route, ",{"type":24,"tag":32,"props":473,"children":475},{"className":474},[],[476],{"type":29,"value":477},"\u002Fapi\u002Ftour\u002Fmcp",{"type":29,"value":479},", using the SDK's Streamable HTTP transport (",{"type":24,"tag":32,"props":481,"children":483},{"className":482},[],[484],{"type":29,"value":485},"@modelcontextprotocol\u002Fsdk",{"type":29,"value":487}," 1.26 is already in ",{"type":24,"tag":32,"props":489,"children":491},{"className":490},[],[492],{"type":29,"value":493},"mcp\u002F",{"type":29,"value":495},"). It's a separate server from the brand MCP (",{"type":24,"tag":32,"props":497,"children":499},{"className":498},[],[500],{"type":29,"value":501},"qpoint-brand",{"type":29,"value":503},", stdio).",{"type":24,"tag":115,"props":505,"children":506},{},[507,512,514,520,522,528,530,535,537,542],{"type":24,"tag":97,"props":508,"children":509},{},[510],{"type":29,"value":511},"Channel.",{"type":29,"value":513}," The open tab subscribes to ",{"type":24,"tag":32,"props":515,"children":517},{"className":516},[],[518],{"type":29,"value":519},"\u002Fapi\u002Ftour\u002Fchannel",{"type":29,"value":521}," (SSE) and posts results back to ",{"type":24,"tag":32,"props":523,"children":525},{"className":524},[],[526],{"type":29,"value":527},"\u002Fapi\u002Ftour\u002Freply",{"type":29,"value":529},". A tool call becomes a command to the tab, which runs it through ",{"type":24,"tag":32,"props":531,"children":533},{"className":532},[],[534],{"type":29,"value":276},{"type":29,"value":536}," and replies with ",{"type":24,"tag":32,"props":538,"children":540},{"className":539},[],[541],{"type":29,"value":442},{"type":29,"value":67},{"type":24,"tag":115,"props":544,"children":545},{},[546,551,553,559,560,566,567,573,574,580,581,587,588,594,595,601,602,608,609,615,616,622,623,629,630,636],{"type":24,"tag":97,"props":547,"children":548},{},[549],{"type":29,"value":550},"Tools",{"type":29,"value":552}," (kebab case, like ",{"type":24,"tag":32,"props":554,"children":556},{"className":555},[],[557],{"type":29,"value":558},"get-color",{"type":29,"value":140},{"type":24,"tag":32,"props":561,"children":563},{"className":562},[],[564],{"type":29,"value":565},"list-pages",{"type":29,"value":148},{"type":24,"tag":32,"props":568,"children":570},{"className":569},[],[571],{"type":29,"value":572},"list-tours",{"type":29,"value":148},{"type":24,"tag":32,"props":575,"children":577},{"className":576},[],[578],{"type":29,"value":579},"read-step",{"type":29,"value":148},{"type":24,"tag":32,"props":582,"children":584},{"className":583},[],[585],{"type":29,"value":586},"start-tour",{"type":29,"value":148},{"type":24,"tag":32,"props":589,"children":591},{"className":590},[],[592],{"type":29,"value":593},"go-to-step",{"type":29,"value":148},{"type":24,"tag":32,"props":596,"children":598},{"className":597},[],[599],{"type":29,"value":600},"next-step",{"type":29,"value":148},{"type":24,"tag":32,"props":603,"children":605},{"className":604},[],[606],{"type":29,"value":607},"previous-step",{"type":29,"value":148},{"type":24,"tag":32,"props":610,"children":612},{"className":611},[],[613],{"type":29,"value":614},"end-tour",{"type":29,"value":148},{"type":24,"tag":32,"props":617,"children":619},{"className":618},[],[620],{"type":29,"value":621},"set-view",{"type":29,"value":148},{"type":24,"tag":32,"props":624,"children":626},{"className":625},[],[627],{"type":29,"value":628},"highlight",{"type":29,"value":148},{"type":24,"tag":32,"props":631,"children":633},{"className":632},[],[634],{"type":29,"value":635},"tour-state",{"type":29,"value":67},{"type":24,"tag":115,"props":638,"children":639},{},[640,645,647,652],{"type":24,"tag":97,"props":641,"children":642},{},[643],{"type":29,"value":644},"Pairing.",{"type":29,"value":646}," In the lab, the most recently focused tab wins, and ",{"type":24,"tag":32,"props":648,"children":650},{"className":649},[],[651],{"type":29,"value":565},{"type":29,"value":653}," shows every connected tab so an agent can pick. In qdash, the person's sign-in pairs the agent with their own tabs: the MCP endpoint authenticates as the person, and the channel only reaches that person's tabs.",{"type":24,"tag":115,"props":655,"children":656},{},[657,662,664,669],{"type":24,"tag":97,"props":658,"children":659},{},[660],{"type":29,"value":661},"Who's driving.",{"type":29,"value":663}," The panel says so: \"Driven by Claude Code\", from the client name the harness sends when it connects. The person can take over by clicking any tour control, and the agent sees that in ",{"type":24,"tag":32,"props":665,"children":667},{"className":666},[],[668],{"type":29,"value":635},{"type":29,"value":67},{"type":24,"tag":265,"props":671,"children":673},{"id":672},"rules-proposed",[674],{"type":29,"value":675},"Rules (proposed)",{"type":24,"tag":677,"props":678,"children":679},"ol",{},[680,705,715,732],{"type":24,"tag":115,"props":681,"children":682},{},[683,688,690,696,698,703],{"type":24,"tag":97,"props":684,"children":685},{},[686],{"type":29,"value":687},"Actions stay with the person.",{"type":29,"value":689}," A drill sends real messages, and ",{"type":24,"tag":32,"props":691,"children":693},{"className":692},[],[694],{"type":29,"value":695},"stage",{"type":29,"value":697}," writes to the draft. The agent can navigate, highlight, read and explain. For a step's action it can only point at the button (\"press Simulate violation when you're ready\"). ",{"type":24,"tag":32,"props":699,"children":701},{"className":700},[],[702],{"type":29,"value":579},{"type":29,"value":704}," names the action, and no tool runs it. That suits a governance product: an agent shouldn't be able to set off a customer's paging tool.",{"type":24,"tag":115,"props":706,"children":707},{},[708,713],{"type":24,"tag":97,"props":709,"children":710},{},[711],{"type":29,"value":712},"The person's clicks win.",{"type":29,"value":714}," If the person moves the tour, the agent's next call works from the new state rather than undoing the move.",{"type":24,"tag":115,"props":716,"children":717},{},[718,723,725,730],{"type":24,"tag":97,"props":719,"children":720},{},[721],{"type":29,"value":722},"No dashboard changes.",{"type":29,"value":724}," The bridge lives in the tour layer. Pages still carry ",{"type":24,"tag":32,"props":726,"children":728},{"className":727},[],[729],{"type":29,"value":214},{"type":29,"value":731}," and nothing else.",{"type":24,"tag":115,"props":733,"children":734},{},[735,740,742,748,750,756],{"type":24,"tag":97,"props":736,"children":737},{},[738],{"type":29,"value":739},"The static deploy can't relay.",{"type":29,"value":741}," design.internal is ",{"type":24,"tag":32,"props":743,"children":745},{"className":744},[],[746],{"type":29,"value":747},"nuxt generate",{"type":29,"value":749}," on Cloudflare Pages, so step 2 runs on dev ",{"type":24,"tag":32,"props":751,"children":753},{"className":752},[],[754],{"type":29,"value":755},":3000",{"type":29,"value":757}," only. Putting it on the deploy needs a Worker with a Durable Object for the channel; that waits for a reason. Step 1 works on the deploy as it is.",{"type":24,"tag":105,"props":759,"children":761},{"id":760},"testing-it-before-the-actual-app",[762],{"type":29,"value":15},{"type":24,"tag":25,"props":764,"children":765},{},[766,768,773,775,781],{"type":29,"value":767},"Each rung runs on the design site first, against the lab's composed mocks. Nothing goes to qdash until rungs 1–5 hold. Use the running ",{"type":24,"tag":32,"props":769,"children":771},{"className":770},[],[772],{"type":29,"value":755},{"type":29,"value":774},"; never start a second ",{"type":24,"tag":32,"props":776,"children":778},{"className":777},[],[779],{"type":29,"value":780},"nuxt dev",{"type":29,"value":782}," in this tree.",{"type":24,"tag":290,"props":784,"children":785},{},[786,807],{"type":24,"tag":294,"props":787,"children":788},{},[789],{"type":24,"tag":298,"props":790,"children":791},{},[792,797,802],{"type":24,"tag":302,"props":793,"children":794},{},[795],{"type":29,"value":796},"Rung",{"type":24,"tag":302,"props":798,"children":799},{},[800],{"type":29,"value":801},"What it proves",{"type":24,"tag":302,"props":803,"children":804},{},[805],{"type":29,"value":806},"How",{"type":24,"tag":313,"props":808,"children":809},{},[810,837,898,943,990,1026,1068],{"type":24,"tag":298,"props":811,"children":812},{},[813,821,826],{"type":24,"tag":320,"props":814,"children":815},{},[816],{"type":24,"tag":97,"props":817,"children":818},{},[819],{"type":29,"value":820},"0. The demo page",{"type":24,"tag":320,"props":822,"children":823},{},[824],{"type":29,"value":825},"The bridge can be seen working, not just believed",{"type":24,"tag":320,"props":827,"children":828},{},[829,835],{"type":24,"tag":32,"props":830,"children":832},{"className":831},[],[833],{"type":29,"value":834},"\u002Fpages\u002Fphase4\u002Ftour-mcp",{"type":29,"value":836},": connection status, connected tabs, a live log of each command (what the agent asked, what the page did, the state it returned), the config snippet to paste into a harness, and a button that sends each tool's sample call from the page itself. \"The demo is the test.\"",{"type":24,"tag":298,"props":838,"children":839},{},[840,848,858],{"type":24,"tag":320,"props":841,"children":842},{},[843],{"type":24,"tag":97,"props":844,"children":845},{},[846],{"type":29,"value":847},"1. Page API, scripted",{"type":24,"tag":320,"props":849,"children":850},{},[851,856],{"type":24,"tag":32,"props":852,"children":854},{"className":853},[],[855],{"type":29,"value":276},{"type":29,"value":857}," does what the panel does",{"type":24,"tag":320,"props":859,"children":860},{},[861,867,869,875,877,882,884,889,890,896],{"type":24,"tag":32,"props":862,"children":864},{"className":863},[],[865],{"type":29,"value":866},"scripts\u002Ftour-drive-check.mjs",{"type":29,"value":868}," (Playwright, in the shape of ",{"type":24,"tag":32,"props":870,"children":872},{"className":871},[],[873],{"type":29,"value":874},"qdash-r31-check.mjs",{"type":29,"value":876},"). It starts the tour, walks ",{"type":24,"tag":97,"props":878,"children":879},{},[880],{"type":29,"value":881},"every step",{"type":29,"value":883},", and at each one asserts the route, the step id, and that each named target is on the page and ringed (a ring's box over the target's box). It tries every view switch, plus ",{"type":24,"tag":32,"props":885,"children":887},{"className":886},[],[888],{"type":29,"value":628},{"type":29,"value":242},{"type":24,"tag":32,"props":891,"children":893},{"className":892},[],[894],{"type":29,"value":895},"end",{"type":29,"value":897},". Walking every step also works as W1's missing-ID check, at run time.",{"type":24,"tag":298,"props":899,"children":900},{},[901,909,914],{"type":24,"tag":320,"props":902,"children":903},{},[904],{"type":24,"tag":97,"props":905,"children":906},{},[907],{"type":29,"value":908},"2. MCP contract, no agent",{"type":24,"tag":320,"props":910,"children":911},{},[912],{"type":29,"value":913},"The endpoint and the channel do what the tools say",{"type":24,"tag":320,"props":915,"children":916},{},[917,919,925,927,933,935,941],{"type":29,"value":918},"The same script opens a tab and connects an SDK ",{"type":24,"tag":32,"props":920,"children":922},{"className":921},[],[923],{"type":29,"value":924},"Client",{"type":29,"value":926}," over Streamable HTTP. It calls every tool and asserts the tab changed. Hand checks use the MCP Inspector (",{"type":24,"tag":32,"props":928,"children":930},{"className":929},[],[931],{"type":29,"value":932},"npx @modelcontextprotocol\u002Finspector",{"type":29,"value":934}," → ",{"type":24,"tag":32,"props":936,"children":938},{"className":937},[],[939],{"type":29,"value":940},"http:\u002F\u002Flocalhost:3000\u002Fapi\u002Ftour\u002Fmcp",{"type":29,"value":942},").",{"type":24,"tag":298,"props":944,"children":945},{},[946,954,959],{"type":24,"tag":320,"props":947,"children":948},{},[949],{"type":24,"tag":97,"props":950,"children":951},{},[952],{"type":29,"value":953},"3. Error cases",{"type":24,"tag":320,"props":955,"children":956},{},[957],{"type":29,"value":958},"It fails plainly",{"type":24,"tag":320,"props":960,"children":961},{},[962,967,969,974,976,981,983,988],{"type":24,"tag":97,"props":963,"children":964},{},[965],{"type":29,"value":966},"Empty:",{"type":29,"value":968}," no tab connected; no tour running. ",{"type":24,"tag":97,"props":970,"children":971},{},[972],{"type":29,"value":973},"Error:",{"type":29,"value":975}," unknown tour or step; a step whose target is missing (it answers with the step and \"not on the page\", no ring); the tab closed or reloaded mid-call (timeout, then a clear message); two tabs open (",{"type":24,"tag":32,"props":977,"children":979},{"className":978},[],[980],{"type":29,"value":565},{"type":29,"value":982},", then an explicit pick). ",{"type":24,"tag":97,"props":984,"children":985},{},[986],{"type":29,"value":987},"Overflow:",{"type":29,"value":989}," a long tour, a step with many targets, a fast run of calls (they queue and finish in order). Each case also has a button on the demo page.",{"type":24,"tag":298,"props":991,"children":992},{},[993,1001,1006],{"type":24,"tag":320,"props":994,"children":995},{},[996],{"type":24,"tag":97,"props":997,"children":998},{},[999],{"type":29,"value":1000},"4. Safety",{"type":24,"tag":320,"props":1002,"children":1003},{},[1004],{"type":29,"value":1005},"The rules hold",{"type":24,"tag":320,"props":1007,"children":1008},{},[1009,1011,1017,1019,1024],{"type":29,"value":1010},"No tool runs ",{"type":24,"tag":32,"props":1012,"children":1014},{"className":1013},[],[1015],{"type":29,"value":1016},"drill",{"type":29,"value":1018}," or ",{"type":24,"tag":32,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":29,"value":695},{"type":29,"value":1025},"; the script asserts the delivery log and the draft are unchanged after a full agent walk. The panel shows \"Driven by …\". A person's click mid-walk is reported back, not undone.",{"type":24,"tag":298,"props":1027,"children":1028},{},[1029,1037,1042],{"type":24,"tag":320,"props":1030,"children":1031},{},[1032],{"type":24,"tag":97,"props":1033,"children":1034},{},[1035],{"type":29,"value":1036},"5. A real harness",{"type":24,"tag":320,"props":1038,"children":1039},{},[1040],{"type":29,"value":1041},"An agent can actually guide someone",{"type":24,"tag":320,"props":1043,"children":1044},{},[1045,1047,1053,1054,1060,1061,1066],{"type":29,"value":1046},"Claude Code with an http entry in ",{"type":24,"tag":32,"props":1048,"children":1050},{"className":1049},[],[1051],{"type":29,"value":1052},".mcp.json",{"type":29,"value":132},{"type":24,"tag":32,"props":1055,"children":1057},{"className":1056},[],[1058],{"type":29,"value":1059},"qpoint-tour",{"type":29,"value":934},{"type":24,"tag":32,"props":1062,"children":1064},{"className":1063},[],[1065],{"type":29,"value":940},{"type":29,"value":1067},"), given one prompt: \"Walk me through how Qpoint covers MCP risk.\" Record it (capture or GIF) as the objective's end-to-end demo. Then a second harness (Claude Desktop or Cursor) with the same config, to show it isn't tied to one harness.",{"type":24,"tag":298,"props":1069,"children":1070},{},[1071,1079,1084],{"type":24,"tag":320,"props":1072,"children":1073},{},[1074],{"type":24,"tag":97,"props":1075,"children":1076},{},[1077],{"type":29,"value":1078},"6. App parity",{"type":24,"tag":320,"props":1080,"children":1081},{},[1082],{"type":29,"value":1083},"The port needs only an adapter and a sign-in",{"type":24,"tag":320,"props":1085,"children":1086},{},[1087,1089,1095],{"type":29,"value":1088},"The rung 1–4 script takes a base URL and a tour id, so after the port it runs against qdash ",{"type":24,"tag":32,"props":1090,"children":1092},{"className":1091},[],[1093],{"type":29,"value":1094},":3030",{"type":29,"value":1096}," unchanged. What differs there is the adapter, the sign-in on the endpoint, and where the IDs are.",{"type":24,"tag":105,"props":1098,"children":1100},{"id":1099},"order-of-work-once-the-tour-files-are-quiet",[1101],{"type":29,"value":16},{"type":24,"tag":677,"props":1103,"children":1104},{},[1105,1122,1143,1155],{"type":24,"tag":115,"props":1106,"children":1107},{},[1108,1113,1114,1120],{"type":24,"tag":32,"props":1109,"children":1111},{"className":1110},[],[1112],{"type":29,"value":276},{"type":29,"value":132},{"type":24,"tag":32,"props":1115,"children":1117},{"className":1116},[],[1118],{"type":29,"value":1119},"plugins\u002Ftour-api.client.ts",{"type":29,"value":1121},"), the demo page with the page-side log, and rung 1's script.",{"type":24,"tag":115,"props":1123,"children":1124},{},[1125,1127,1133,1135,1141],{"type":29,"value":1126},"The Nitro endpoint and channel, ",{"type":24,"tag":32,"props":1128,"children":1130},{"className":1129},[],[1131],{"type":29,"value":1132},"useTourBridge",{"type":29,"value":1134}," in ",{"type":24,"tag":32,"props":1136,"children":1138},{"className":1137},[],[1139],{"type":29,"value":1140},"TourHost",{"type":29,"value":1142},", \"Driven by\" on the panels, and rungs 2–4.",{"type":24,"tag":115,"props":1144,"children":1145},{},[1146,1148,1153],{"type":29,"value":1147},"The ",{"type":24,"tag":32,"props":1149,"children":1151},{"className":1150},[],[1152],{"type":29,"value":1052},{"type":29,"value":1154}," entry and rung 5's recorded demo.",{"type":24,"tag":115,"props":1156,"children":1157},{},[1158],{"type":29,"value":1159},"Record the outcome in CYCLE.md and tour-layer.md, then hand step 1's API to W2's hardening and the endpoint's sign-in to the qdash port.",{"type":24,"tag":105,"props":1161,"children":1163},{"id":1162},"built-2026-10-29-the-same-day",[1164],{"type":29,"value":17},{"type":24,"tag":25,"props":1166,"children":1167},{},[1168],{"type":29,"value":1169},"Steps 1–3 of the order of work. Rungs 0–5 pass on the design site's dev server.",{"type":24,"tag":290,"props":1171,"children":1172},{},[1173,1189],{"type":24,"tag":294,"props":1174,"children":1175},{},[1176],{"type":24,"tag":298,"props":1177,"children":1178},{},[1179,1184],{"type":24,"tag":302,"props":1180,"children":1181},{},[1182],{"type":29,"value":1183},"Piece",{"type":24,"tag":302,"props":1185,"children":1186},{},[1187],{"type":29,"value":1188},"File",{"type":24,"tag":313,"props":1190,"children":1191},{},[1192,1224,1265,1290,1330,1347,1363],{"type":24,"tag":298,"props":1193,"children":1194},{},[1195,1215],{"type":24,"tag":320,"props":1196,"children":1197},{},[1198,1200,1205,1207,1213],{"type":29,"value":1199},"Page API, ",{"type":24,"tag":32,"props":1201,"children":1203},{"className":1202},[],[1204],{"type":29,"value":276},{"type":29,"value":1206}," (and ",{"type":24,"tag":32,"props":1208,"children":1210},{"className":1209},[],[1211],{"type":29,"value":1212},"window.qpTourTab",{"type":29,"value":1214},", the tab's relay id)",{"type":24,"tag":320,"props":1216,"children":1217},{},[1218],{"type":24,"tag":32,"props":1219,"children":1221},{"className":1220},[],[1222],{"type":29,"value":1223},"app\u002Fcomposables\u002FuseTourApi.ts",{"type":24,"tag":298,"props":1225,"children":1226},{},[1227,1232],{"type":24,"tag":320,"props":1228,"children":1229},{},[1230],{"type":29,"value":1231},"The tab's side: installs the API, connects to the relay on the dev server, draws the agent's highlight ring and the \"Driven by …\" pill, reports the person's own moves",{"type":24,"tag":320,"props":1233,"children":1234},{},[1235,1241,1242,1248,1250,1256,1257,1263],{"type":24,"tag":32,"props":1236,"children":1238},{"className":1237},[],[1239],{"type":29,"value":1240},"app\u002Fcomponents\u002Ftour\u002FAgent.vue",{"type":29,"value":132},{"type":24,"tag":32,"props":1243,"children":1245},{"className":1244},[],[1246],{"type":29,"value":1247},"\u003CTourAgent \u002F>",{"type":29,"value":1249},", mounted beside ",{"type":24,"tag":32,"props":1251,"children":1253},{"className":1252},[],[1254],{"type":29,"value":1255},"\u003CTourHost \u002F>",{"type":29,"value":1134},{"type":24,"tag":32,"props":1258,"children":1260},{"className":1259},[],[1261],{"type":29,"value":1262},"layouts\u002Fgovernance-mock.vue",{"type":29,"value":1264},")",{"type":24,"tag":298,"props":1266,"children":1267},{},[1268,1273],{"type":24,"tag":320,"props":1269,"children":1270},{},[1271],{"type":29,"value":1272},"The relay: tabs, pending calls, the log; local origins only",{"type":24,"tag":320,"props":1274,"children":1275},{},[1276,1282,1284],{"type":24,"tag":32,"props":1277,"children":1279},{"className":1278},[],[1280],{"type":29,"value":1281},"server\u002Futils\u002FtourRelay.ts",{"type":29,"value":1283},"; ",{"type":24,"tag":32,"props":1285,"children":1287},{"className":1286},[],[1288],{"type":29,"value":1289},"server\u002Fapi\u002Ftour\u002F{channel.get,reply.post,command.post,log.get}.ts",{"type":24,"tag":298,"props":1291,"children":1292},{},[1293,1298],{"type":24,"tag":320,"props":1294,"children":1295},{},[1296],{"type":29,"value":1297},"The MCP endpoint: Streamable HTTP, one session per harness, 11 tools, guide instructions",{"type":24,"tag":320,"props":1299,"children":1300},{},[1301,1307,1308,1313,1315,1321,1323,1329],{"type":24,"tag":32,"props":1302,"children":1304},{"className":1303},[],[1305],{"type":29,"value":1306},"server\u002Fapi\u002Ftour\u002Fmcp.ts",{"type":29,"value":132},{"type":24,"tag":32,"props":1309,"children":1311},{"className":1310},[],[1312],{"type":29,"value":485},{"type":29,"value":1314}," 1.26 and ",{"type":24,"tag":32,"props":1316,"children":1318},{"className":1317},[],[1319],{"type":29,"value":1320},"zod",{"type":29,"value":1322}," added to design's ",{"type":24,"tag":32,"props":1324,"children":1326},{"className":1325},[],[1327],{"type":29,"value":1328},"package.json",{"type":29,"value":1264},{"type":24,"tag":298,"props":1331,"children":1332},{},[1333,1338],{"type":24,"tag":320,"props":1334,"children":1335},{},[1336],{"type":29,"value":1337},"Rung 0, the demo page: the lab embedded at 1440 × 900 and scaled, connected pages, sample calls (they drive the embedded lab), the log, the harness config",{"type":24,"tag":320,"props":1339,"children":1340},{},[1341],{"type":24,"tag":32,"props":1342,"children":1344},{"className":1343},[],[1345],{"type":29,"value":1346},"app\u002Fpages\u002Fpages\u002Fphase4\u002Ftour-mcp.vue",{"type":24,"tag":298,"props":1348,"children":1349},{},[1350,1355],{"type":24,"tag":320,"props":1351,"children":1352},{},[1353],{"type":29,"value":1354},"Rungs 1–4, scripted: 62 checks",{"type":24,"tag":320,"props":1356,"children":1357},{},[1358],{"type":24,"tag":32,"props":1359,"children":1361},{"className":1360},[],[1362],{"type":29,"value":866},{"type":24,"tag":298,"props":1364,"children":1365},{},[1366,1371],{"type":24,"tag":320,"props":1367,"children":1368},{},[1369],{"type":29,"value":1370},"Rung 5, Claude Code end to end",{"type":24,"tag":320,"props":1372,"children":1373},{},[1374],{"type":24,"tag":56,"props":1375,"children":1377},{"href":1376},"\u002Fcycles\u002Fdesign\u002Fc125\u002Fdoc\u002Fmcp-guide-rung5",[1378],{"type":24,"tag":32,"props":1379,"children":1381},{"className":1380},[],[1382],{"type":29,"value":1383},"mcp-guide-rung5.md",{"type":24,"tag":25,"props":1385,"children":1386},{},[1387],{"type":24,"tag":97,"props":1388,"children":1389},{},[1390],{"type":29,"value":1391},"How the build differs from the plan above:",{"type":24,"tag":111,"props":1393,"children":1394},{},[1395,1426,1464,1480],{"type":24,"tag":115,"props":1396,"children":1397},{},[1398,1410,1412,1417,1419,1424],{"type":24,"tag":97,"props":1399,"children":1400},{},[1401,1403,1408],{"type":29,"value":1402},"The endpoint lives at ",{"type":24,"tag":32,"props":1404,"children":1406},{"className":1405},[],[1407],{"type":29,"value":477},{"type":29,"value":1409},",",{"type":29,"value":1411}," as planned. The channel is ",{"type":24,"tag":32,"props":1413,"children":1415},{"className":1414},[],[1416],{"type":29,"value":519},{"type":29,"value":1418},", but the tab answers on ",{"type":24,"tag":32,"props":1420,"children":1422},{"className":1421},[],[1423],{"type":29,"value":527},{"type":29,"value":1425},", which also carries focus and the person's moves.",{"type":24,"tag":115,"props":1427,"children":1428},{},[1429,1447,1449,1455,1457,1462],{"type":24,"tag":97,"props":1430,"children":1431},{},[1432,1434,1439,1440,1446],{"type":29,"value":1433},"No change to ",{"type":24,"tag":32,"props":1435,"children":1437},{"className":1436},[],[1438],{"type":29,"value":1140},{"type":29,"value":1018},{"type":24,"tag":32,"props":1441,"children":1443},{"className":1442},[],[1444],{"type":29,"value":1445},"useTour",{"type":29,"value":67},{"type":29,"value":1448}," The panel-iterations thread had both open. The API starts a tour with ",{"type":24,"tag":32,"props":1450,"children":1452},{"className":1451},[],[1453],{"type":29,"value":1454},"useTour().start",{"type":29,"value":1456}," and then ",{"type":24,"tag":32,"props":1458,"children":1460},{"className":1459},[],[1461],{"type":29,"value":154},{"type":29,"value":1463},", so the host does the routing and the glide as it would for its own Next.",{"type":24,"tag":115,"props":1465,"children":1466},{},[1467,1472,1473,1478],{"type":24,"tag":97,"props":1468,"children":1469},{},[1470],{"type":29,"value":1471},"Agent narration stays in chat.",{"type":29,"value":226},{"type":24,"tag":32,"props":1474,"children":1476},{"className":1475},[],[1477],{"type":29,"value":628},{"type":29,"value":1479}," draws a ring and nothing else, with no callout text.",{"type":24,"tag":115,"props":1481,"children":1482},{},[1483,1488,1490,1496,1498,1503],{"type":24,"tag":97,"props":1484,"children":1485},{},[1486],{"type":29,"value":1487},"A script drives only its own tab.",{"type":29,"value":1489}," Commands without a ",{"type":24,"tag":32,"props":1491,"children":1493},{"className":1492},[],[1494],{"type":29,"value":1495},"tabId",{"type":29,"value":1497}," go to the most recently focused tab. While this was built, three of someone's own lab tabs were connected to the relay. So the script always passes the ",{"type":24,"tag":32,"props":1499,"children":1501},{"className":1500},[],[1502],{"type":29,"value":1495},{"type":29,"value":1504}," of the tab it opened, and the demo page's sample calls pass the embedded lab's.",{"type":24,"tag":25,"props":1506,"children":1507},{},[1508,1513,1515,1521],{"type":24,"tag":97,"props":1509,"children":1510},{},[1511],{"type":29,"value":1512},"Rung 5.",{"type":29,"value":1514}," Claude Code (",{"type":24,"tag":32,"props":1516,"children":1518},{"className":1517},[],[1519],{"type":29,"value":1520},"claude -p",{"type":29,"value":1522},", Sonnet, only this server) was asked to walk stop 2 one step at a time. It found the tour and moved the page. It read each step and explained it with the person's numbers (\"14 calls would have paused, 3 people would have been affected\"). Then it stopped for \"Next.\" At Tune and Drill it pointed at the button and said it hadn't pressed it. Total cost about $0.35. Not yet done: a recorded capture, and a second harness.",{"type":24,"tag":25,"props":1524,"children":1525},{},[1526],{"type":24,"tag":97,"props":1527,"children":1528},{},[1529],{"type":29,"value":1530},"Not covered yet:",{"type":24,"tag":111,"props":1532,"children":1533},{},[1534,1551,1561,1588],{"type":24,"tag":115,"props":1535,"children":1536},{},[1537,1542,1544,1550],{"type":24,"tag":97,"props":1538,"children":1539},{},[1540],{"type":29,"value":1541},"No connected tab at all.",{"type":29,"value":1543}," The scripts can't test that while other tabs are open; the message exists in ",{"type":24,"tag":32,"props":1545,"children":1547},{"className":1546},[],[1548],{"type":29,"value":1549},"sendToTour",{"type":29,"value":67},{"type":24,"tag":115,"props":1552,"children":1553},{},[1554,1559],{"type":24,"tag":97,"props":1555,"children":1556},{},[1557],{"type":29,"value":1558},"A paused background tab.",{"type":29,"value":1560}," Browsers pause timers in background tabs; the relay times out after 10 s with a message that says so.",{"type":24,"tag":115,"props":1562,"children":1563},{},[1564,1578,1580,1586],{"type":24,"tag":1565,"props":1566,"children":1567},"del",{},[1568],{"type":24,"tag":97,"props":1569,"children":1570},{},[1571,1576],{"type":24,"tag":32,"props":1572,"children":1574},{"className":1573},[],[1575],{"type":29,"value":747},{"type":29,"value":1577}," with the SDK added.",{"type":29,"value":1579}," Passed on the 2026-10-29 deploy (",{"type":24,"tag":32,"props":1581,"children":1583},{"className":1582},[],[1584],{"type":29,"value":1585},"f351ccdf7c",{"type":29,"value":1587},"), with no prerender exclusions. The relay stays dev-only: on the deployed site the demo page loads and nothing drives it.",{"type":24,"tag":115,"props":1589,"children":1590},{},[1591,1596,1598,1604],{"type":24,"tag":97,"props":1592,"children":1593},{},[1594],{"type":29,"value":1595},"Not in the page registry.",{"type":29,"value":1597}," Discoverable only by URL until the panel-iterations hunks in ",{"type":24,"tag":32,"props":1599,"children":1601},{"className":1600},[],[1602],{"type":29,"value":1603},"page-registry.ts",{"type":29,"value":1605}," are committed.",{"type":24,"tag":25,"props":1607,"children":1608},{},[1609],{"type":24,"tag":97,"props":1610,"children":1611},{},[1612],{"type":29,"value":1613},"Run them again:",{"type":24,"tag":1615,"props":1616,"children":1622},"pre",{"className":1617,"code":1618,"language":1619,"meta":1620,"style":1621},"language-bash","node scripts\u002Ftour-drive-check.mjs\n","bash","","undefined",[1623],{"type":24,"tag":32,"props":1624,"children":1625},{"__ignoreMap":1620},[1626],{"type":29,"value":1618},{"type":24,"tag":1615,"props":1628,"children":1630},{"className":1617,"code":1629,"language":1619,"meta":1620,"style":1621},"claude mcp add --transport http qpoint-guide http:\u002F\u002Flocalhost:3000\u002Fapi\u002Ftour\u002Fmcp\n",[1631],{"type":24,"tag":32,"props":1632,"children":1633},{"__ignoreMap":1620},[1634],{"type":29,"value":1629},{"type":24,"tag":105,"props":1636,"children":1638},{"id":1637},"the-unscripted-guide-written-up-2026-10-29-not-built",[1639],{"type":29,"value":18},{"type":24,"tag":25,"props":1641,"children":1642},{},[1643,1645],{"type":29,"value":1644},"Mark, after the build: ",{"type":24,"tag":41,"props":1646,"children":1647},{},[1648,1650,1656],{"type":29,"value":1649},"\"how feasible is a non-scripted tour? I fire up my agent, point it at the mcp, and ask ",{"type":24,"tag":32,"props":1651,"children":1653},{"className":1652},[],[1654],{"type":29,"value":1655},"Where do I go to add a slack integration?",{"type":29,"value":1657}," Can we use the callout component for something like that?\"",{"type":24,"tag":25,"props":1659,"children":1660},{},[1661,1666],{"type":24,"tag":97,"props":1662,"children":1663},{},[1664],{"type":29,"value":1665},"Feasible, and yes, the callout fits.",{"type":29,"value":1667}," A \"where do I go\" question is a short tour the agent makes up on the spot: find the thing, ring the way there, open the page, point at the row with a sentence. The relay, the ring, \"Driven by …\" and the person's-click-wins rule carry over unchanged. What's missing is something to search, a way to open any page, a way to point with words, and IDs on the rail.",{"type":24,"tag":265,"props":1669,"children":1671},{"id":1670},"the-walk-for-the-slack-question",[1672],{"type":29,"value":1673},"The walk, for the Slack question",{"type":24,"tag":677,"props":1675,"children":1676},{},[1677,1719,1729,1747],{"type":24,"tag":115,"props":1678,"children":1679},{},[1680,1685,1687,1693,1695,1701,1703,1709,1711,1717],{"type":24,"tag":97,"props":1681,"children":1682},{},[1683],{"type":29,"value":1684},"Find.",{"type":29,"value":1686}," The agent calls ",{"type":24,"tag":32,"props":1688,"children":1690},{"className":1689},[],[1691],{"type":29,"value":1692},"find-in-app",{"type":29,"value":1694}," with \"slack\". It gets Admin › Integrations, the Notifications table (",{"type":24,"tag":32,"props":1696,"children":1698},{"className":1697},[],[1699],{"type":29,"value":1700},"integrations.channels",{"type":29,"value":1702},"), and the row ",{"type":24,"tag":32,"props":1704,"children":1706},{"className":1705},[],[1707],{"type":29,"value":1708},"integrations.channel",{"type":29,"value":1710}," keyed ",{"type":24,"tag":32,"props":1712,"children":1714},{"className":1713},[],[1715],{"type":29,"value":1716},"slack",{"type":29,"value":1718},", each with a one-line description.",{"type":24,"tag":115,"props":1720,"children":1721},{},[1722,1727],{"type":24,"tag":97,"props":1723,"children":1724},{},[1725],{"type":29,"value":1726},"The way there.",{"type":29,"value":1728}," It points at the rail's Integrations item, with the callout titled \"Admin › Integrations\". After a moment it opens the page.",{"type":24,"tag":115,"props":1730,"children":1731},{},[1732,1737,1739,1745],{"type":24,"tag":97,"props":1733,"children":1734},{},[1735],{"type":29,"value":1736},"The place.",{"type":29,"value":1738}," It points at the Slack row with \"Slack sends the findings whose severity you tick to a channel. Connect it here.\" ",{"type":24,"tag":32,"props":1740,"children":1742},{"className":1741},[],[1743],{"type":29,"value":1744},"point",{"type":29,"value":1746}," returns the region's visible text, so the agent can see the row's live state.",{"type":24,"tag":115,"props":1748,"children":1749},{},[1750,1755,1757,1763],{"type":24,"tag":97,"props":1751,"children":1752},{},[1753],{"type":29,"value":1754},"The answer, honestly.",{"type":29,"value":1756}," In the lab's fixture, Slack is already connected and sends high and medium findings to ",{"type":24,"tag":32,"props":1758,"children":1760},{"className":1759},[],[1761],{"type":29,"value":1762},"#sec-alerts",{"type":29,"value":1764},". So the right answer is \"it's already set up; this row is where you change it\", not \"press Connect\". The agent explains this in chat. Connect is for the person to press.",{"type":24,"tag":265,"props":1766,"children":1768},{"id":1767},"whats-already-there",[1769],{"type":29,"value":1770},"What's already there",{"type":24,"tag":111,"props":1772,"children":1773},{},[1774,1806,1842],{"type":24,"tag":115,"props":1775,"children":1776},{},[1777,1788,1790,1796,1798,1804],{"type":24,"tag":97,"props":1778,"children":1779},{},[1780,1786],{"type":24,"tag":32,"props":1781,"children":1783},{"className":1782},[],[1784],{"type":29,"value":1785},"TourCallout",{"type":29,"value":1787}," works on any region.",{"type":29,"value":1789}," It takes a box, a number, text and an optional title. In v4 it draws ",{"type":24,"tag":32,"props":1791,"children":1793},{"className":1792},[],[1794],{"type":29,"value":1795},"TourMarker",{"type":29,"value":1797}," placed by ",{"type":24,"tag":32,"props":1799,"children":1801},{"className":1800},[],[1802],{"type":29,"value":1803},"TourFloat",{"type":29,"value":1805},", on whichever side fits with its pointer aimed at the region. Nothing in it depends on a tour step.",{"type":24,"tag":115,"props":1807,"children":1808},{},[1809,1817,1819,1824,1826,1832,1834,1840],{"type":24,"tag":97,"props":1810,"children":1811},{},[1812],{"type":24,"tag":32,"props":1813,"children":1815},{"className":1814},[],[1816],{"type":29,"value":628},{"type":29,"value":1818}," rings any ",{"type":24,"tag":32,"props":1820,"children":1822},{"className":1821},[],[1823],{"type":29,"value":214},{"type":29,"value":1825},", optionally narrowed to ",{"type":24,"tag":32,"props":1827,"children":1829},{"className":1828},[],[1830],{"type":29,"value":1831},"data-qp-key",{"type":29,"value":1833}," rows and grown to an ancestor (",{"type":24,"tag":32,"props":1835,"children":1837},{"className":1836},[],[1838],{"type":29,"value":1839},"expand: \"tr\"",{"type":29,"value":1841},"). It's cleared on the next move.",{"type":24,"tag":115,"props":1843,"children":1844},{},[1845,1850,1852,1857,1858,1863,1865,1871],{"type":24,"tag":97,"props":1846,"children":1847},{},[1848],{"type":29,"value":1849},"59 IDs on the lab pages.",{"type":29,"value":1851}," Integrations already has ",{"type":24,"tag":32,"props":1853,"children":1855},{"className":1854},[],[1856],{"type":29,"value":1700},{"type":29,"value":148},{"type":24,"tag":32,"props":1859,"children":1861},{"className":1860},[],[1862],{"type":29,"value":1708},{"type":29,"value":1864}," (keyed by channel id) and ",{"type":24,"tag":32,"props":1866,"children":1868},{"className":1867},[],[1869],{"type":29,"value":1870},"integrations.deliveries",{"type":29,"value":67},{"type":24,"tag":265,"props":1873,"children":1875},{"id":1874},"whats-missing",[1876],{"type":29,"value":1877},"What's missing",{"type":24,"tag":290,"props":1879,"children":1880},{},[1881,1897],{"type":24,"tag":294,"props":1882,"children":1883},{},[1884],{"type":24,"tag":298,"props":1885,"children":1886},{},[1887,1892],{"type":24,"tag":302,"props":1888,"children":1889},{},[1890],{"type":29,"value":1891},"Gap",{"type":24,"tag":302,"props":1893,"children":1894},{},[1895],{"type":29,"value":1896},"Fix",{"type":24,"tag":313,"props":1898,"children":1899},{},[1900,1932,1977,2038,2085],{"type":24,"tag":298,"props":1901,"children":1902},{},[1903,1908],{"type":24,"tag":320,"props":1904,"children":1905},{},[1906],{"type":29,"value":1907},"Nothing to search. The agent can only read tour steps. A page that isn't open isn't rendered, so the tab can't search it.",{"type":24,"tag":320,"props":1909,"children":1910},{},[1911,1916,1917,1923,1925,1930],{"type":24,"tag":97,"props":1912,"children":1913},{},[1914],{"type":29,"value":1915},"An app map",{"type":29,"value":148},{"type":24,"tag":32,"props":1918,"children":1920},{"className":1919},[],[1921],{"type":29,"value":1922},"app\u002Fdata\u002Fapp-map.ts",{"type":29,"value":1924},": each page's id, route and rail path, and its IDs, each with a title and a one-line body. This is the annotation registry from Objective 1 (title, body, how to use, related ids), started from the agent's side. Help mode and the agent then read from one source. It's plain data with no ",{"type":24,"tag":32,"props":1926,"children":1928},{"className":1927},[],[1929],{"type":29,"value":248},{"type":29,"value":1931},", so the server can read it with no tab open.",{"type":24,"tag":298,"props":1933,"children":1934},{},[1935,1940],{"type":24,"tag":320,"props":1936,"children":1937},{},[1938],{"type":29,"value":1939},"Only a tour step's page can be reached.",{"type":24,"tag":320,"props":1941,"children":1942},{},[1943,1952,1953,1959,1961,1967,1969,1975],{"type":24,"tag":97,"props":1944,"children":1945},{},[1946],{"type":24,"tag":32,"props":1947,"children":1949},{"className":1948},[],[1950],{"type":29,"value":1951},"open-page",{"type":29,"value":226},{"type":24,"tag":32,"props":1954,"children":1956},{"className":1955},[],[1957],{"type":29,"value":1958},"{ page }",{"type":29,"value":1960},": any page in the map. The host doesn't need a tour running; the API calls ",{"type":24,"tag":32,"props":1962,"children":1964},{"className":1963},[],[1965],{"type":29,"value":1966},"navigateTo",{"type":29,"value":1968}," and waits for the page's first ID, as ",{"type":24,"tag":32,"props":1970,"children":1972},{"className":1971},[],[1973],{"type":29,"value":1974},"settle()",{"type":29,"value":1976}," does.",{"type":24,"tag":298,"props":1978,"children":1979},{},[1980,1990],{"type":24,"tag":320,"props":1981,"children":1982},{},[1983,1988],{"type":24,"tag":32,"props":1984,"children":1986},{"className":1985},[],[1987],{"type":29,"value":628},{"type":29,"value":1989}," rings but says nothing.",{"type":24,"tag":320,"props":1991,"children":1992},{},[1993,2001,2002,2008,2010,2015,2017,2022,2024,2030,2032,2037],{"type":24,"tag":97,"props":1994,"children":1995},{},[1996],{"type":24,"tag":32,"props":1997,"children":1999},{"className":1998},[],[2000],{"type":29,"value":1744},{"type":29,"value":226},{"type":24,"tag":32,"props":2003,"children":2005},{"className":2004},[],[2006],{"type":29,"value":2007},"{ id, key?, expand?, title?, text }",{"type":29,"value":2009},": a ring plus a ",{"type":24,"tag":32,"props":2011,"children":2013},{"className":2012},[],[2014],{"type":29,"value":1785},{"type":29,"value":2016}," (v4's ",{"type":24,"tag":32,"props":2018,"children":2020},{"className":2019},[],[2021],{"type":29,"value":1795},{"type":29,"value":2023},"). It returns ",{"type":24,"tag":32,"props":2025,"children":2027},{"className":2026},[],[2028],{"type":29,"value":2029},"matched",{"type":29,"value":2031}," and the region's visible text. It's cleared on the next move or the next ",{"type":24,"tag":32,"props":2033,"children":2035},{"className":2034},[],[2036],{"type":29,"value":1744},{"type":29,"value":67},{"type":24,"tag":298,"props":2039,"children":2040},{},[2041,2046],{"type":24,"tag":320,"props":2042,"children":2043},{},[2044],{"type":29,"value":2045},"The way there has no IDs.",{"type":24,"tag":320,"props":2047,"children":2048},{},[2049,2054,2055,2061,2063,2069,2071,2077,2079,2084],{"type":24,"tag":97,"props":2050,"children":2051},{},[2052],{"type":29,"value":2053},"IDs on the rail items",{"type":29,"value":132},{"type":24,"tag":32,"props":2056,"children":2058},{"className":2057},[],[2059],{"type":29,"value":2060},"rail.\u003Cpage-id>",{"type":29,"value":2062},", in ",{"type":24,"tag":32,"props":2064,"children":2066},{"className":2065},[],[2067],{"type":29,"value":2068},"GovernanceMockSidebar",{"type":29,"value":2070},") and on the channel row's Connect button (",{"type":24,"tag":32,"props":2072,"children":2074},{"className":2073},[],[2075],{"type":29,"value":2076},"integrations.channel.connect",{"type":29,"value":2078},", keyed). This is the same protocol: the pages still carry ",{"type":24,"tag":32,"props":2080,"children":2082},{"className":2081},[],[2083],{"type":29,"value":214},{"type":29,"value":731},{"type":24,"tag":298,"props":2086,"children":2087},{},[2088,2093],{"type":24,"tag":320,"props":2089,"children":2090},{},[2091],{"type":29,"value":2092},"A full tour panel is too much for a two-hop answer.",{"type":24,"tag":320,"props":2094,"children":2095},{},[2096,2101,2103,2109],{"type":24,"tag":97,"props":2097,"children":2098},{},[2099],{"type":29,"value":2100},"No panel.",{"type":29,"value":2102}," An unscripted walk is rings and callouts only, with the \"Driven by …\" pill. Whether a longer one should borrow the panel, as a ",{"type":24,"tag":32,"props":2104,"children":2106},{"className":2105},[],[2107],{"type":29,"value":2108},"compose-tour",{"type":29,"value":2110}," tool, waits for what testing shows (see Open).",{"type":24,"tag":25,"props":2112,"children":2113},{},[2114,2119,2121,2127,2129,2134],{"type":24,"tag":32,"props":2115,"children":2117},{"className":2116},[],[2118],{"type":29,"value":1692},{"type":29,"value":2120}," searches the map on the server. A cheaper fallback, ",{"type":24,"tag":32,"props":2122,"children":2124},{"className":2123},[],[2125],{"type":29,"value":2126},"read-page",{"type":29,"value":2128},", would return the IDs on the open page with their visible text. That answers \"what's this?\" without a map, but not \"where do I go?\", so the map is the real piece and ",{"type":24,"tag":32,"props":2130,"children":2132},{"className":2131},[],[2133],{"type":29,"value":2126},{"type":29,"value":2135}," is optional.",{"type":24,"tag":265,"props":2137,"children":2139},{"id":2138},"rules-as-amended",[2140],{"type":29,"value":2141},"Rules, as amended",{"type":24,"tag":677,"props":2143,"children":2144},{},[2145,2161,2192,2209],{"type":24,"tag":115,"props":2146,"children":2147},{},[2148,2152,2154,2159],{"type":24,"tag":97,"props":2149,"children":2150},{},[2151],{"type":29,"value":687},{"type":29,"value":2153}," Unchanged: ",{"type":24,"tag":32,"props":2155,"children":2157},{"className":2156},[],[2158],{"type":29,"value":1744},{"type":29,"value":2160}," can aim at Connect, and nothing presses it.",{"type":24,"tag":115,"props":2162,"children":2163},{},[2164,2168,2170,2175,2177,2182,2184,2190],{"type":24,"tag":97,"props":2165,"children":2166},{},[2167],{"type":29,"value":712},{"type":29,"value":2169}," If the person navigates away mid-walk, the agent's next ",{"type":24,"tag":32,"props":2171,"children":2173},{"className":2172},[],[2174],{"type":29,"value":1744},{"type":29,"value":2176}," answers \"not on the page\" rather than taking them back. ",{"type":24,"tag":32,"props":2178,"children":2180},{"className":2179},[],[2181],{"type":29,"value":635},{"type":29,"value":2183}," (or a new ",{"type":24,"tag":32,"props":2185,"children":2187},{"className":2186},[],[2188],{"type":29,"value":2189},"page-state",{"type":29,"value":2191},") reports where they are.",{"type":24,"tag":115,"props":2193,"children":2194},{},[2195,2200,2202,2207],{"type":24,"tag":97,"props":2196,"children":2197},{},[2198],{"type":29,"value":2199},"A short label on screen, the explanation in chat.",{"type":29,"value":2201}," This changes \"agent narration stays in chat\". ",{"type":24,"tag":32,"props":2203,"children":2205},{"className":2204},[],[2206],{"type":29,"value":1744},{"type":29,"value":2208}," puts a title and one sentence on the page, so the person can see where to look without switching windows. Anything longer stays in chat. Callout text is capped (about 140 characters); longer text is refused, not truncated.",{"type":24,"tag":115,"props":2210,"children":2211},{},[2212,2217,2219,2224],{"type":24,"tag":97,"props":2213,"children":2214},{},[2215],{"type":29,"value":2216},"Honest state.",{"type":29,"value":2218}," The agent reads what's there before it advises. ",{"type":24,"tag":32,"props":2220,"children":2222},{"className":2221},[],[2223],{"type":29,"value":1744},{"type":29,"value":2225}," returns the region's text for that reason, and the map's descriptions say what a region shows, never what it's set to.",{"type":24,"tag":265,"props":2227,"children":2229},{"id":2228},"testing-it",[2230],{"type":29,"value":2231},"Testing it",{"type":24,"tag":25,"props":2233,"children":2234},{},[2235],{"type":29,"value":2236},"The same ladder as above, on the lab first:",{"type":24,"tag":290,"props":2238,"children":2239},{},[2240,2254],{"type":24,"tag":294,"props":2241,"children":2242},{},[2243],{"type":24,"tag":298,"props":2244,"children":2245},{},[2246,2250],{"type":24,"tag":302,"props":2247,"children":2248},{},[2249],{"type":29,"value":796},{"type":24,"tag":302,"props":2251,"children":2252},{},[2253],{"type":29,"value":806},{"type":24,"tag":313,"props":2255,"children":2256},{},[2257,2300,2336,2381,2404],{"type":24,"tag":298,"props":2258,"children":2259},{},[2260,2268],{"type":24,"tag":320,"props":2261,"children":2262},{},[2263],{"type":24,"tag":97,"props":2264,"children":2265},{},[2266],{"type":29,"value":2267},"U0. Demo page",{"type":24,"tag":320,"props":2269,"children":2270},{},[2271,2276,2278,2284,2285,2291,2292,2298],{"type":24,"tag":32,"props":2272,"children":2274},{"className":2273},[],[2275],{"type":29,"value":834},{"type":29,"value":2277}," gains sample calls ",{"type":24,"tag":32,"props":2279,"children":2281},{"className":2280},[],[2282],{"type":29,"value":2283},"find-in-app \"slack\"",{"type":29,"value":148},{"type":24,"tag":32,"props":2286,"children":2288},{"className":2287},[],[2289],{"type":29,"value":2290},"open-page integrations",{"type":29,"value":242},{"type":24,"tag":32,"props":2293,"children":2295},{"className":2294},[],[2296],{"type":29,"value":2297},"point integrations.channel slack",{"type":29,"value":2299},", and a box to type a question for the map.",{"type":24,"tag":298,"props":2301,"children":2302},{},[2303,2311],{"type":24,"tag":320,"props":2304,"children":2305},{},[2306],{"type":24,"tag":97,"props":2307,"children":2308},{},[2309],{"type":29,"value":2310},"U1. Scripted",{"type":24,"tag":320,"props":2312,"children":2313},{},[2314,2320,2322,2327,2329,2334],{"type":24,"tag":32,"props":2315,"children":2317},{"className":2316},[],[2318],{"type":29,"value":2319},"tour-drive-check.mjs",{"type":29,"value":2321}," checks that every map entry's ID exists on its page (the map can't drift from the pages; a missing-ID check like W1's), that ",{"type":24,"tag":32,"props":2323,"children":2325},{"className":2324},[],[2326],{"type":29,"value":1951},{"type":29,"value":2328}," reaches each page, and that ",{"type":24,"tag":32,"props":2330,"children":2332},{"className":2331},[],[2333],{"type":29,"value":1744},{"type":29,"value":2335}," draws a ring and a callout over the region, inside the viewport, with its pointer aimed at it.",{"type":24,"tag":298,"props":2337,"children":2338},{},[2339,2347],{"type":24,"tag":320,"props":2340,"children":2341},{},[2342],{"type":24,"tag":97,"props":2343,"children":2344},{},[2345],{"type":29,"value":2346},"U2. Contract",{"type":24,"tag":320,"props":2348,"children":2349},{},[2350,2352,2357,2359,2365,2366,2372,2373,2379],{"type":29,"value":2351},"The MCP client calls the new tools. ",{"type":24,"tag":32,"props":2353,"children":2355},{"className":2354},[],[2356],{"type":29,"value":2283},{"type":29,"value":2358}," ranks Integrations' Slack row first. ",{"type":24,"tag":32,"props":2360,"children":2362},{"className":2361},[],[2363],{"type":29,"value":2364},"\"add a teammate\"",{"type":29,"value":148},{"type":24,"tag":32,"props":2367,"children":2369},{"className":2368},[],[2370],{"type":29,"value":2371},"\"pause an MCP server\"",{"type":29,"value":242},{"type":24,"tag":32,"props":2374,"children":2376},{"className":2375},[],[2377],{"type":29,"value":2378},"\"where's my spend\"",{"type":29,"value":2380}," land on the expected pages.",{"type":24,"tag":298,"props":2382,"children":2383},{},[2384,2392],{"type":24,"tag":320,"props":2385,"children":2386},{},[2387],{"type":24,"tag":97,"props":2388,"children":2389},{},[2390],{"type":29,"value":2391},"U3. Errors",{"type":24,"tag":320,"props":2393,"children":2394},{},[2395,2397,2402],{"type":29,"value":2396},"No match (\"nothing in the map for that\", plus the closest pages). An ambiguous query (several results, not a guess). ",{"type":24,"tag":32,"props":2398,"children":2400},{"className":2399},[],[2401],{"type":29,"value":1744},{"type":29,"value":2403}," at an ID that isn't on the open page. A callout text that's too long. The person navigating away mid-walk.",{"type":24,"tag":298,"props":2405,"children":2406},{},[2407,2415],{"type":24,"tag":320,"props":2408,"children":2409},{},[2410],{"type":24,"tag":97,"props":2411,"children":2412},{},[2413],{"type":29,"value":2414},"U4. A real harness",{"type":24,"tag":320,"props":2416,"children":2417},{},[2418,2420,2425,2427,2432],{"type":29,"value":2419},"Claude Code, asked exactly ",{"type":24,"tag":41,"props":2421,"children":2422},{},[2423],{"type":29,"value":2424},"\"Where do I go to add a Slack integration?\"",{"type":29,"value":2426},", with nothing else in its prompt. The pass is: it rings the rail, opens Integrations, points at the Slack row, says it's already connected to ",{"type":24,"tag":32,"props":2428,"children":2430},{"className":2429},[],[2431],{"type":29,"value":1762},{"type":29,"value":2433},", and doesn't claim to have connected anything. Then three more questions from the U2 set, and one the map can't answer. Record a capture.",{"type":24,"tag":265,"props":2435,"children":2437},{"id":2436},"order-of-work",[2438],{"type":29,"value":2439},"Order of work",{"type":24,"tag":677,"props":2441,"children":2442},{},[2443,2456,2501,2532],{"type":24,"tag":115,"props":2444,"children":2445},{},[2446,2448,2454],{"type":29,"value":2447},"Write the map for the lab pages: the 59 IDs plus the rail. Most of the effort is the one-line bodies, written in the voice of ",{"type":24,"tag":32,"props":2449,"children":2451},{"className":2450},[],[2452],{"type":29,"value":2453},"governance-model.vue",{"type":29,"value":2455},". It's the same content help mode needs.",{"type":24,"tag":115,"props":2457,"children":2458},{},[2459,2461,2466,2467,2472,2473,2479,2480,2486,2488,2494,2495,2500],{"type":29,"value":2460},"Add the rail and Connect IDs, then ",{"type":24,"tag":32,"props":2462,"children":2464},{"className":2463},[],[2465],{"type":29,"value":1951},{"type":29,"value":242},{"type":24,"tag":32,"props":2468,"children":2470},{"className":2469},[],[2471],{"type":29,"value":1744},{"type":29,"value":1134},{"type":24,"tag":32,"props":2474,"children":2476},{"className":2475},[],[2477],{"type":29,"value":2478},"useTourApi",{"type":29,"value":242},{"type":24,"tag":32,"props":2481,"children":2483},{"className":2482},[],[2484],{"type":29,"value":2485},"TourAgent",{"type":29,"value":2487}," (point reuses ",{"type":24,"tag":32,"props":2489,"children":2491},{"className":2490},[],[2492],{"type":29,"value":2493},"TourRing",{"type":29,"value":242},{"type":24,"tag":32,"props":2496,"children":2498},{"className":2497},[],[2499],{"type":29,"value":1785},{"type":29,"value":942},{"type":24,"tag":115,"props":2502,"children":2503},{},[2504,2506,2511,2512,2517,2518,2523,2525,2530],{"type":29,"value":2505},"Add ",{"type":24,"tag":32,"props":2507,"children":2509},{"className":2508},[],[2510],{"type":29,"value":1692},{"type":29,"value":148},{"type":24,"tag":32,"props":2513,"children":2515},{"className":2514},[],[2516],{"type":29,"value":1951},{"type":29,"value":242},{"type":24,"tag":32,"props":2519,"children":2521},{"className":2520},[],[2522],{"type":29,"value":1744},{"type":29,"value":2524}," to ",{"type":24,"tag":32,"props":2526,"children":2528},{"className":2527},[],[2529],{"type":29,"value":1306},{"type":29,"value":2531},", and amend the instructions: point, then explain in chat, never press.",{"type":24,"tag":115,"props":2533,"children":2534},{},[2535],{"type":29,"value":2536},"Run U0–U4, then record the outcome here and in CYCLE.md.",{"type":24,"tag":25,"props":2538,"children":2539},{},[2540,2545,2546,2551],{"type":24,"tag":32,"props":2541,"children":2543},{"className":2542},[],[2544],{"type":29,"value":1140},{"type":29,"value":242},{"type":24,"tag":32,"props":2547,"children":2549},{"className":2548},[],[2550],{"type":29,"value":1445},{"type":29,"value":2552}," stay untouched, as in the first build.",{"type":24,"tag":265,"props":2554,"children":2556},{"id":2555},"built-2026-10-29-the-same-afternoon",[2557],{"type":29,"value":2558},"Built (2026-10-29, the same afternoon)",{"type":24,"tag":25,"props":2560,"children":2561},{},[2562,2564,2569,2571,2576],{"type":29,"value":2563},"Mark: ",{"type":24,"tag":41,"props":2565,"children":2566},{},[2567],{"type":29,"value":2568},"\"Build it.\"",{"type":29,"value":2570}," All of U0–U4 pass. ",{"type":24,"tag":32,"props":2572,"children":2574},{"className":2573},[],[2575],{"type":29,"value":866},{"type":29,"value":2577}," passes 166 checks: rungs 1–4 for the tour, U1–U3 for the walk.",{"type":24,"tag":290,"props":2579,"children":2580},{},[2581,2595],{"type":24,"tag":294,"props":2582,"children":2583},{},[2584],{"type":24,"tag":298,"props":2585,"children":2586},{},[2587,2591],{"type":24,"tag":302,"props":2588,"children":2589},{},[2590],{"type":29,"value":1183},{"type":24,"tag":302,"props":2592,"children":2593},{},[2594],{"type":29,"value":1188},{"type":24,"tag":313,"props":2596,"children":2597},{},[2598,2627,2674,2710,2750,2775,2813,2830,2859],{"type":24,"tag":298,"props":2599,"children":2600},{},[2601,2619],{"type":24,"tag":320,"props":2602,"children":2603},{},[2604,2606,2612,2613],{"type":29,"value":2605},"The app map: 29 pages (18 composed, 11 blank rail items), 66 regions and their rows, ",{"type":24,"tag":32,"props":2607,"children":2609},{"className":2608},[],[2610],{"type":29,"value":2611},"searchMap",{"type":29,"value":148},{"type":24,"tag":32,"props":2614,"children":2616},{"className":2615},[],[2617],{"type":29,"value":2618},"mapPage",{"type":24,"tag":320,"props":2620,"children":2621},{},[2622],{"type":24,"tag":32,"props":2623,"children":2625},{"className":2624},[],[2626],{"type":29,"value":1922},{"type":24,"tag":298,"props":2628,"children":2629},{},[2630,2666],{"type":24,"tag":320,"props":2631,"children":2632},{},[2633,2639,2640,2646,2647,2653,2654,2659,2661],{"type":24,"tag":32,"props":2634,"children":2636},{"className":2635},[],[2637],{"type":29,"value":2638},"find",{"type":29,"value":148},{"type":24,"tag":32,"props":2641,"children":2643},{"className":2642},[],[2644],{"type":29,"value":2645},"readPage",{"type":29,"value":148},{"type":24,"tag":32,"props":2648,"children":2650},{"className":2649},[],[2651],{"type":29,"value":2652},"openPage",{"type":29,"value":148},{"type":24,"tag":32,"props":2655,"children":2657},{"className":2656},[],[2658],{"type":29,"value":1744},{"type":29,"value":2660}," on ",{"type":24,"tag":32,"props":2662,"children":2664},{"className":2663},[],[2665],{"type":29,"value":276},{"type":24,"tag":320,"props":2667,"children":2668},{},[2669],{"type":24,"tag":32,"props":2670,"children":2672},{"className":2671},[],[2673],{"type":29,"value":1223},{"type":24,"tag":298,"props":2675,"children":2676},{},[2677,2702],{"type":24,"tag":320,"props":2678,"children":2679},{},[2680,2682,2687,2689,2694,2695,2700],{"type":29,"value":2681},"The pointer, drawn as ",{"type":24,"tag":32,"props":2683,"children":2685},{"className":2684},[],[2686],{"type":29,"value":2493},{"type":29,"value":2688}," plus v4's ",{"type":24,"tag":32,"props":2690,"children":2692},{"className":2691},[],[2693],{"type":29,"value":1795},{"type":29,"value":1797},{"type":24,"tag":32,"props":2696,"children":2698},{"className":2697},[],[2699],{"type":29,"value":1803},{"type":29,"value":2701},". It reports the person's own navigation during a walk, and a tab now runs one command at a time, in order",{"type":24,"tag":320,"props":2703,"children":2704},{},[2705],{"type":24,"tag":32,"props":2706,"children":2708},{"className":2707},[],[2709],{"type":29,"value":1240},{"type":24,"tag":298,"props":2711,"children":2712},{},[2713,2742],{"type":24,"tag":320,"props":2714,"children":2715},{},[2716,2721,2723,2728,2729,2734,2735,2740],{"type":24,"tag":32,"props":2717,"children":2719},{"className":2718},[],[2720],{"type":29,"value":1692},{"type":29,"value":2722}," (answered on the server), ",{"type":24,"tag":32,"props":2724,"children":2726},{"className":2725},[],[2727],{"type":29,"value":2126},{"type":29,"value":148},{"type":24,"tag":32,"props":2730,"children":2732},{"className":2731},[],[2733],{"type":29,"value":1951},{"type":29,"value":148},{"type":24,"tag":32,"props":2736,"children":2738},{"className":2737},[],[2739],{"type":29,"value":1744},{"type":29,"value":2741},"; the instructions gain the walk (server 0.2.0, 15 tools)",{"type":24,"tag":320,"props":2743,"children":2744},{},[2745],{"type":24,"tag":32,"props":2746,"children":2748},{"className":2747},[],[2749],{"type":29,"value":1306},{"type":24,"tag":298,"props":2751,"children":2752},{},[2753,2766],{"type":24,"tag":320,"props":2754,"children":2755},{},[2756,2758,2764],{"type":29,"value":2757},"Rail IDs: ",{"type":24,"tag":32,"props":2759,"children":2761},{"className":2760},[],[2762],{"type":29,"value":2763},"rail",{"type":29,"value":2765},", keyed by qdash path, on every item and disclosure",{"type":24,"tag":320,"props":2767,"children":2768},{},[2769],{"type":24,"tag":32,"props":2770,"children":2772},{"className":2771},[],[2773],{"type":29,"value":2774},"app\u002Fcomponents\u002Fgovernance\u002Fmock\u002FSidebar.vue",{"type":24,"tag":298,"props":2776,"children":2777},{},[2778,2797],{"type":24,"tag":320,"props":2779,"children":2780},{},[2781,2787,2789,2795],{"type":24,"tag":32,"props":2782,"children":2784},{"className":2783},[],[2785],{"type":29,"value":2786},"integrations.connect",{"type":29,"value":2788}," (keyed by channel) and ",{"type":24,"tag":32,"props":2790,"children":2792},{"className":2791},[],[2793],{"type":29,"value":2794},"integrations.connector",{"type":29,"value":2796}," (keyed by connector id, the only change to the copied qdash markup)",{"type":24,"tag":320,"props":2798,"children":2799},{},[2800,2806,2807],{"type":24,"tag":32,"props":2801,"children":2803},{"className":2802},[],[2804],{"type":29,"value":2805},"mock\u002Fintegrations.vue",{"type":29,"value":148},{"type":24,"tag":32,"props":2808,"children":2810},{"className":2809},[],[2811],{"type":29,"value":2812},"governance\u002Flive\u002FIntegrationsConnectors.vue",{"type":24,"tag":298,"props":2814,"children":2815},{},[2816,2821],{"type":24,"tag":320,"props":2817,"children":2818},{},[2819],{"type":29,"value":2820},"U0: a second row of samples and an \"Ask the map\" box",{"type":24,"tag":320,"props":2822,"children":2823},{},[2824],{"type":24,"tag":32,"props":2825,"children":2827},{"className":2826},[],[2828],{"type":29,"value":2829},"pages\u002Fphase4\u002Ftour-mcp.vue",{"type":24,"tag":298,"props":2831,"children":2832},{},[2833,2851],{"type":24,"tag":320,"props":2834,"children":2835},{},[2836,2838,2844,2845],{"type":29,"value":2837},"U1–U3, and ",{"type":24,"tag":32,"props":2839,"children":2841},{"className":2840},[],[2842],{"type":29,"value":2843},"--only walk",{"type":29,"value":364},{"type":24,"tag":32,"props":2846,"children":2848},{"className":2847},[],[2849],{"type":29,"value":2850},"--only tour",{"type":24,"tag":320,"props":2852,"children":2853},{},[2854],{"type":24,"tag":32,"props":2855,"children":2857},{"className":2856},[],[2858],{"type":29,"value":866},{"type":24,"tag":298,"props":2860,"children":2861},{},[2862,2873],{"type":24,"tag":320,"props":2863,"children":2864},{},[2865,2867],{"type":29,"value":2866},"U4: ask any question through Claude Code on a headless lab tab of its own; screenshots, the stream and ",{"type":24,"tag":32,"props":2868,"children":2870},{"className":2869},[],[2871],{"type":29,"value":2872},"answer.md",{"type":24,"tag":320,"props":2874,"children":2875},{},[2876],{"type":24,"tag":32,"props":2877,"children":2879},{"className":2878},[],[2880],{"type":29,"value":2881},"scripts\u002Ftour-guide-ask.mjs",{"type":24,"tag":25,"props":2883,"children":2884},{},[2885,2890,2892,2901],{"type":24,"tag":97,"props":2886,"children":2887},{},[2888],{"type":29,"value":2889},"U4: three questions, asked exactly as written",{"type":29,"value":2891}," (Sonnet, about $0.17 each; answers and captures in ",{"type":24,"tag":56,"props":2893,"children":2895},{"href":2894},"mcp-guide-u4\u002F",[2896],{"type":24,"tag":32,"props":2897,"children":2899},{"className":2898},[],[2900],{"type":29,"value":2894},{"type":29,"value":2902},"):",{"type":24,"tag":111,"props":2904,"children":2905},{},[2906,2957,2967],{"type":24,"tag":115,"props":2907,"children":2908},{},[2909,2913,2915,2920,2921,2926,2928,2934,2936,2941,2943,2948,2950,2956],{"type":24,"tag":41,"props":2910,"children":2911},{},[2912],{"type":29,"value":2424},{"type":29,"value":2914}," The agent called ",{"type":24,"tag":32,"props":2916,"children":2918},{"className":2917},[],[2919],{"type":29,"value":1692},{"type":29,"value":47},{"type":24,"tag":32,"props":2922,"children":2924},{"className":2923},[],[2925],{"type":29,"value":2290},{"type":29,"value":2927},", which rang the rail's Integrations item with \"Admin › Integrations\" (",{"type":24,"tag":56,"props":2929,"children":2931},{"href":2930},"mcp-guide-u4\u002Fslack-1-the-way.png",[2932],{"type":29,"value":2933},"the way",{"type":29,"value":2935},"). It pointed at the Slack connector card with no text and read it. It answered that Slack is already connected (active, 21 high and 1 medium routed), that ",{"type":24,"tag":97,"props":2937,"children":2938},{},[2939],{"type":29,"value":2940},"config",{"type":29,"value":2942}," on the card changes it, that the routing row below sets severities, and that other connectors have ",{"type":24,"tag":97,"props":2944,"children":2945},{},[2946],{"type":29,"value":2947},"+",{"type":29,"value":2949},". It pressed nothing (",{"type":24,"tag":56,"props":2951,"children":2953},{"href":2952},"mcp-guide-u4\u002Fslack-2-the-card.png",[2954],{"type":29,"value":2955},"the card",{"type":29,"value":942},{"type":24,"tag":115,"props":2958,"children":2959},{},[2960,2965],{"type":24,"tag":41,"props":2961,"children":2962},{},[2963],{"type":29,"value":2964},"\"How do I set a spend limit so a runaway day becomes a finding?\"",{"type":29,"value":2966}," It went to Cost Center and pointed at the Spend guardrail. It read that no ceiling is set and the policy is off, and gave the card's suggested $400 a day with its reason. It noted that the card doesn't say whether the ceiling can block or only record.",{"type":24,"tag":115,"props":2968,"children":2969},{},[2970,2975,2977,2982],{"type":24,"tag":41,"props":2971,"children":2972},{},[2973],{"type":29,"value":2974},"\"Where do I install the sensor on our laptops?\"",{"type":29,"value":2976}," It went to Endpoints › Add endpoints, pointed at the test-machine step, and gave the order: download, one test machine, first signal, MDM. It said the text it read stopped partway through step 4: ",{"type":24,"tag":32,"props":2978,"children":2980},{"className":2979},[],[2981],{"type":29,"value":1744},{"type":29,"value":2983}," returns at most 500 characters.",{"type":24,"tag":25,"props":2985,"children":2986},{},[2987],{"type":24,"tag":97,"props":2988,"children":2989},{},[2990],{"type":29,"value":2991},"What testing changed:",{"type":24,"tag":111,"props":2993,"children":2994},{},[2995,3005,3029,3039,3078],{"type":24,"tag":115,"props":2996,"children":2997},{},[2998,3003],{"type":24,"tag":97,"props":2999,"children":3000},{},[3001],{"type":29,"value":3002},"Read before advising.",{"type":29,"value":3004}," In the first run the agent's first callout said \"Press + to add it\". It corrected that once it had read the card. The instructions now say to point with a title only, read the text, and then write the sentence. The second run did that.",{"type":24,"tag":115,"props":3006,"children":3007},{},[3008,3013,3015,3020,3022,3027],{"type":24,"tag":97,"props":3009,"children":3010},{},[3011],{"type":29,"value":3012},"A callout covered its own target",{"type":29,"value":3014}," when the target sat on the right edge. Outside a tour nothing tells ",{"type":24,"tag":32,"props":3016,"children":3018},{"className":3017},[],[3019],{"type":29,"value":1803},{"type":29,"value":3021}," what to avoid, so ",{"type":24,"tag":32,"props":3023,"children":3025},{"className":3024},[],[3026],{"type":29,"value":2485},{"type":29,"value":3028}," now provides the pointer's region as the obstacle.",{"type":24,"tag":115,"props":3030,"children":3031},{},[3032,3037],{"type":24,"tag":97,"props":3033,"children":3034},{},[3035],{"type":29,"value":3036},"Commands queue.",{"type":29,"value":3038}," A burst of calls passed by luck before; the tab now runs them one at a time.",{"type":24,"tag":115,"props":3040,"children":3041},{},[3042,3047,3049,3055,3056,3062,3063,3069,3070,3076],{"type":24,"tag":97,"props":3043,"children":3044},{},[3045],{"type":29,"value":3046},"The map caught drift on its first run.",{"type":29,"value":3048}," The c123 tours thread ported qdash's pages into the lab while this was being built: Home, Integrations, Cost, the MCP server detail, Findings, and a new MCP Servers listing. U1 reported every region and row the map named that a page no longer had. The map now follows the ported pages, including the thread's change list (",{"type":24,"tag":32,"props":3050,"children":3052},{"className":3051},[],[3053],{"type":29,"value":3054},"cost.daily",{"type":29,"value":148},{"type":24,"tag":32,"props":3057,"children":3059},{"className":3058},[],[3060],{"type":29,"value":3061},"cost.by-*",{"type":29,"value":148},{"type":24,"tag":32,"props":3064,"children":3066},{"className":3065},[],[3067],{"type":29,"value":3068},"findings.group",{"type":29,"value":148},{"type":24,"tag":32,"props":3071,"children":3073},{"className":3072},[],[3074],{"type":29,"value":3075},"mcp-servers.row",{"type":29,"value":3077},"). The Slack answer is better for it: qdash's connector card is the real place to add one.",{"type":24,"tag":115,"props":3079,"children":3080},{},[3081,3086,3088,3094],{"type":24,"tag":97,"props":3082,"children":3083},{},[3084],{"type":29,"value":3085},"Which tab an agent drives.",{"type":29,"value":3087}," Mark's first run went to the wrong tab. Another session's tour tab had reloaded two seconds before his question, and connecting counted as focus, so that tab took the calls; changing page counted too. Now only the person makes a tab the default: focusing its window, or clicking or typing in it. A tab that connects or changes page doesn't. An automated browser (",{"type":24,"tag":32,"props":3089,"children":3091},{"className":3090},[],[3092],{"type":29,"value":3093},"navigator.webdriver",{"type":29,"value":3095},") never does, so scripts name their tab. With no tab used yet, the agent is told to ask the person to click into theirs. A tab now also reconnects after the dev server restarts its routes, where before it dropped off the relay until reloaded.",{"type":24,"tag":25,"props":3097,"children":3098},{},[3099],{"type":24,"tag":97,"props":3100,"children":3101},{},[3102],{"type":29,"value":1391},{"type":24,"tag":111,"props":3104,"children":3105},{},[3106,3138,3161,3176],{"type":24,"tag":115,"props":3107,"children":3108},{},[3109,3114,3115,3121,3123,3129,3131,3136],{"type":24,"tag":97,"props":3110,"children":3111},{},[3112],{"type":29,"value":3113},"Rail IDs are one id, keyed by path:",{"type":29,"value":226},{"type":24,"tag":32,"props":3116,"children":3118},{"className":3117},[],[3119],{"type":29,"value":3120},"data-qp-id=\"rail\"",{"type":29,"value":3122}," with ",{"type":24,"tag":32,"props":3124,"children":3126},{"className":3125},[],[3127],{"type":29,"value":3128},"data-qp-key=\"\u002Fintegrations\"",{"type":29,"value":3130},", not ",{"type":24,"tag":32,"props":3132,"children":3134},{"className":3133},[],[3135],{"type":29,"value":2060},{"type":29,"value":3137},". It's the same shape as rows.",{"type":24,"tag":115,"props":3139,"children":3140},{},[3141,3151,3153,3159],{"type":24,"tag":97,"props":3142,"children":3143},{},[3144,3149],{"type":24,"tag":32,"props":3145,"children":3147},{"className":3146},[],[3148],{"type":29,"value":1951},{"type":29,"value":3150}," shows the way itself.",{"type":29,"value":3152}," It rings the rail item, or the disclosure if the item's list is closed, with the path as a callout for 1.6 s, then navigates. That answers the \"rail-then-page beat\" question below. ",{"type":24,"tag":32,"props":3154,"children":3156},{"className":3155},[],[3157],{"type":29,"value":3158},"showWay: false",{"type":29,"value":3160}," skips it.",{"type":24,"tag":115,"props":3162,"children":3163},{},[3164,3174],{"type":24,"tag":97,"props":3165,"children":3166},{},[3167,3172],{"type":24,"tag":32,"props":3168,"children":3170},{"className":3169},[],[3171],{"type":29,"value":2126},{"type":29,"value":3173}," was built,",{"type":29,"value":3175}," though the plan made it optional. It's what the map check runs on.",{"type":24,"tag":115,"props":3177,"children":3178},{},[3179,3184,3185,3191],{"type":24,"tag":97,"props":3180,"children":3181},{},[3182],{"type":29,"value":3183},"The pointer is drawn in v4's colours",{"type":29,"value":132},{"type":24,"tag":32,"props":3186,"children":3188},{"className":3187},[],[3189],{"type":29,"value":3190},".qp-tour-v4-scope",{"type":29,"value":3192},") whatever the tour's variant, since no tour is running.",{"type":24,"tag":25,"props":3194,"children":3195},{},[3196,3200],{"type":24,"tag":97,"props":3197,"children":3198},{},[3199],{"type":29,"value":1530},{"type":29,"value":3201}," a second harness; a capture of the whole walk as a GIF (the screenshots are there); questions the map can't answer, asked through a harness; qdash (rung 6 and the app map's source there).",{"type":24,"tag":25,"props":3203,"children":3204},{},[3205],{"type":24,"tag":97,"props":3206,"children":3207},{},[3208],{"type":29,"value":1613},{"type":24,"tag":1615,"props":3210,"children":3212},{"className":1617,"code":3211,"language":1619,"meta":1620,"style":1621},"node scripts\u002Ftour-drive-check.mjs --only walk\n",[3213],{"type":24,"tag":32,"props":3214,"children":3215},{"__ignoreMap":1620},[3216],{"type":29,"value":3211},{"type":24,"tag":1615,"props":3218,"children":3220},{"className":1617,"code":3219,"language":1619,"meta":1620,"style":1621},"zsh -ic 'node scripts\u002Ftour-guide-ask.mjs \"Where do I go to add a Slack integration?\"'\n",[3221],{"type":24,"tag":32,"props":3222,"children":3223},{"__ignoreMap":1620},[3224],{"type":29,"value":3219},{"type":24,"tag":265,"props":3226,"children":3228},{"id":3227},"what-the-dashboard-knows-built-2026-10-29",[3229],{"type":29,"value":3230},"What the dashboard knows (built 2026-10-29)",{"type":24,"tag":25,"props":3232,"children":3233},{},[3234,3236,3241,3243,3248,3249,3254,3256,3261],{"type":29,"value":3235},"Mark asked ",{"type":24,"tag":41,"props":3237,"children":3238},{},[3239],{"type":29,"value":3240},"\"where would I protect SSH keys?\"",{"type":29,"value":3242},". The guide took him to Policies and rang the whole list: the map knew the pages, not what they're for. His follow-up: ",{"type":24,"tag":41,"props":3244,"children":3245},{},[3246],{"type":29,"value":3247},"\"How would we give our MCP more specialized knowledge?\"",{"type":29,"value":47},{"type":24,"tag":41,"props":3250,"children":3251},{},[3252],{"type":29,"value":3253},"\"this is for all dashboard knowledge, not just SSH Keys?\"",{"type":29,"value":3255}," (yes), and ",{"type":24,"tag":41,"props":3257,"children":3258},{},[3259],{"type":29,"value":3260},"\"let's rename both mcp servers qpoint-guide\"",{"type":29,"value":67},{"type":24,"tag":25,"props":3263,"children":3264},{},[3265],{"type":24,"tag":97,"props":3266,"children":3267},{},[3268],{"type":29,"value":3269},"Built:",{"type":24,"tag":111,"props":3271,"children":3272},{},[3273,3308,3341,3383,3398,3416,3437,3517,3533],{"type":24,"tag":115,"props":3274,"children":3275},{},[3276,3285,3287,3293,3295],{"type":24,"tag":97,"props":3277,"children":3278},{},[3279],{"type":24,"tag":32,"props":3280,"children":3282},{"className":3281},[],[3283],{"type":29,"value":3284},"app\u002Fdata\u002Fguide-knowledge.ts",{"type":29,"value":3286}," holds what the dashboard knows, in the words a customer asks with. Most of it is generated from the product's own data, the policy catalog and the frameworks in ",{"type":24,"tag":32,"props":3288,"children":3290},{"className":3289},[],[3291],{"type":29,"value":3292},"governance-fixture.ts",{"type":29,"value":3294},":\n",{"type":24,"tag":111,"props":3296,"children":3297},{},[3298,3303],{"type":24,"tag":115,"props":3299,"children":3300},{},[3301],{"type":29,"value":3302},"each of the 19 policies, with its description, why it matters, what Enforce does, and the requirements it maps to;",{"type":24,"tag":115,"props":3304,"children":3305},{},[3306],{"type":29,"value":3307},"each of the 5 frameworks and its 44 requirements, with the policies that cover them.",{"type":24,"tag":115,"props":3309,"children":3310},{},[3311,3316],{"type":24,"tag":97,"props":3312,"children":3313},{},[3314],{"type":29,"value":3315},"Two parts of that file are hand-written:",{"type":24,"tag":111,"props":3317,"children":3318},{},[3319,3330],{"type":24,"tag":115,"props":3320,"children":3321},{},[3322,3328],{"type":24,"tag":32,"props":3323,"children":3325},{"className":3324},[],[3326],{"type":29,"value":3327},"POLICY_WORDS",{"type":29,"value":3329},": everyday words for each policy (\"ssh keys\", \".env\", \"api keys\", \"human in the loop\", \"deepseek\");",{"type":24,"tag":115,"props":3331,"children":3332},{},[3333,3339],{"type":24,"tag":32,"props":3334,"children":3336},{"className":3335},[],[3337],{"type":29,"value":3338},"CONCEPTS",{"type":29,"value":3340},": 17 terms, each with what it means and where it's seen (Observe, Enforce, exception, draft, drill, source checks and so on).",{"type":24,"tag":115,"props":3342,"children":3343},{},[3344,3349],{"type":24,"tag":97,"props":3345,"children":3346},{},[3347],{"type":29,"value":3348},"The knowledge lives in the map's rows:",{"type":24,"tag":111,"props":3350,"children":3351},{},[3352,3365,3378],{"type":24,"tag":115,"props":3353,"children":3354},{},[3355,3357,3363],{"type":29,"value":3356},"policies on ",{"type":24,"tag":32,"props":3358,"children":3360},{"className":3359},[],[3361],{"type":29,"value":3362},"policies.row",{"type":29,"value":3364},", keyed by policy id, each opening to that policy's page;",{"type":24,"tag":115,"props":3366,"children":3367},{},[3368,3370,3376],{"type":29,"value":3369},"framework requirements on ",{"type":24,"tag":32,"props":3371,"children":3373},{"className":3372},[],[3374],{"type":29,"value":3375},"compliance.framework",{"type":29,"value":3377},";",{"type":24,"tag":115,"props":3379,"children":3380},{},[3381],{"type":29,"value":3382},"concepts come back as their own kind of result.",{"type":24,"tag":115,"props":3384,"children":3385},{},[3386,3396],{"type":24,"tag":97,"props":3387,"children":3388},{},[3389,3394],{"type":24,"tag":32,"props":3390,"children":3392},{"className":3391},[],[3393],{"type":29,"value":1692},{"type":29,"value":3395}," labels each result",{"type":29,"value":3397}," as a page, region, row or concept.",{"type":24,"tag":115,"props":3399,"children":3400},{},[3401,3414],{"type":24,"tag":97,"props":3402,"children":3403},{},[3404,3406,3412],{"type":29,"value":3405},"A new ",{"type":24,"tag":32,"props":3407,"children":3409},{"className":3408},[],[3410],{"type":29,"value":3411},"explain",{"type":29,"value":3413}," tool",{"type":29,"value":3415}," says what a term means. It's answered on the server.",{"type":24,"tag":115,"props":3417,"children":3418},{},[3419,3429,3430,3436],{"type":24,"tag":97,"props":3420,"children":3421},{},[3422,3427],{"type":24,"tag":32,"props":3423,"children":3425},{"className":3424},[],[3426],{"type":29,"value":1951},{"type":29,"value":3428}," takes a record query",{"type":29,"value":132},{"type":24,"tag":32,"props":3431,"children":3433},{"className":3432},[],[3434],{"type":29,"value":3435},"{ policyId }",{"type":29,"value":942},{"type":24,"tag":115,"props":3438,"children":3439},{},[3440,3445,3446,3451,3453,3459,3461,3467,3468,3474,3475,3481,3482,3488,3489,3495,3496,3502,3503,3509,3510,3516],{"type":24,"tag":97,"props":3441,"children":3442},{},[3443],{"type":29,"value":3444},"New IDs:",{"type":29,"value":226},{"type":24,"tag":32,"props":3447,"children":3449},{"className":3448},[],[3450],{"type":29,"value":3362},{"type":29,"value":3452}," on the Control Center's rows (",{"type":24,"tag":32,"props":3454,"children":3456},{"className":3455},[],[3457],{"type":29,"value":3458},"ControlsPolicies.vue",{"type":29,"value":3460},"), and eight section IDs on the policy page (",{"type":24,"tag":32,"props":3462,"children":3464},{"className":3463},[],[3465],{"type":29,"value":3466},"policy.overview",{"type":29,"value":148},{"type":24,"tag":32,"props":3469,"children":3471},{"className":3470},[],[3472],{"type":29,"value":3473},".mode",{"type":29,"value":148},{"type":24,"tag":32,"props":3476,"children":3478},{"className":3477},[],[3479],{"type":29,"value":3480},".configuration",{"type":29,"value":148},{"type":24,"tag":32,"props":3483,"children":3485},{"className":3484},[],[3486],{"type":29,"value":3487},".severity",{"type":29,"value":148},{"type":24,"tag":32,"props":3490,"children":3492},{"className":3491},[],[3493],{"type":29,"value":3494},".exceptions",{"type":29,"value":148},{"type":24,"tag":32,"props":3497,"children":3499},{"className":3498},[],[3500],{"type":29,"value":3501},".frameworks",{"type":29,"value":148},{"type":24,"tag":32,"props":3504,"children":3506},{"className":3505},[],[3507],{"type":29,"value":3508},".findings",{"type":29,"value":148},{"type":24,"tag":32,"props":3511,"children":3513},{"className":3512},[],[3514],{"type":29,"value":3515},".history",{"type":29,"value":942},{"type":24,"tag":115,"props":3518,"children":3519},{},[3520,3525,3526,3531],{"type":24,"tag":97,"props":3521,"children":3522},{},[3523],{"type":29,"value":3524},"A drift check:",{"type":29,"value":226},{"type":24,"tag":32,"props":3527,"children":3529},{"className":3528},[],[3530],{"type":29,"value":2126},{"type":29,"value":3532}," reports any row key the map names that its page doesn't show, so U1 fails if the catalog and the page disagree.",{"type":24,"tag":115,"props":3534,"children":3535},{},[3536,3547,3549,3555,3557,3562],{"type":24,"tag":97,"props":3537,"children":3538},{},[3539,3541],{"type":29,"value":3540},"Renamed to ",{"type":24,"tag":32,"props":3542,"children":3544},{"className":3543},[],[3545],{"type":29,"value":3546},"qpoint-guide",{"type":29,"value":3548}," (server 0.3.0, 16 tools), in the code, the demo page's snippets, ",{"type":24,"tag":32,"props":3550,"children":3552},{"className":3551},[],[3553],{"type":29,"value":3554},"tour-guide-ask.mjs",{"type":29,"value":3556}," and this project's Claude Code registration. The endpoint stays at ",{"type":24,"tag":32,"props":3558,"children":3560},{"className":3559},[],[3561],{"type":29,"value":477},{"type":29,"value":67},{"type":24,"tag":25,"props":3564,"children":3565},{},[3566,3571],{"type":24,"tag":97,"props":3567,"children":3568},{},[3569],{"type":29,"value":3570},"Checks:",{"type":29,"value":3572}," 189 pass. U2 adds knowledge questions:",{"type":24,"tag":111,"props":3574,"children":3575},{},[3576,3581,3586,3591,3596],{"type":24,"tag":115,"props":3577,"children":3578},{},[3579],{"type":29,"value":3580},"\"protect SSH keys\" → P-FILES, with P-CREDENTIALS in the top three;",{"type":24,"tag":115,"props":3582,"children":3583},{},[3584],{"type":29,"value":3585},"\"API keys leaking to the model\" → P-CREDENTIALS;",{"type":24,"tag":115,"props":3587,"children":3588},{},[3589],{"type":29,"value":3590},"\"prompt injection\" → the policy and the LLM01 requirement;",{"type":24,"tag":115,"props":3592,"children":3593},{},[3594],{"type":29,"value":3595},"\"a human to approve deletes\" → P-TOOL-APPROVAL;",{"type":24,"tag":115,"props":3597,"children":3598},{},[3599,3604],{"type":24,"tag":32,"props":3600,"children":3602},{"className":3601},[],[3603],{"type":29,"value":3411},{"type":29,"value":3605},", including a term it doesn't know.",{"type":24,"tag":25,"props":3607,"children":3608},{},[3609,3614,3616,3624],{"type":24,"tag":97,"props":3610,"children":3611},{},[3612],{"type":29,"value":3613},"Claude Code",{"type":29,"value":3615}," (answers in ",{"type":24,"tag":56,"props":3617,"children":3618},{"href":2894},[3619],{"type":24,"tag":32,"props":3620,"children":3622},{"className":3621},[],[3623],{"type":29,"value":2894},{"type":29,"value":2902},{"type":24,"tag":111,"props":3626,"children":3627},{},[3628,3638,3676],{"type":24,"tag":115,"props":3629,"children":3630},{},[3631,3636],{"type":24,"tag":41,"props":3632,"children":3633},{},[3634],{"type":29,"value":3635},"\"Where would I protect SSH keys?\"",{"type":29,"value":3637}," It rang the Restricted file access row (P-FILES) and said what it does and what Enforce does. It added P-CREDENTIALS for a key that's already been read, and pressed nothing.",{"type":24,"tag":115,"props":3639,"children":3640},{},[3641,3646],{"type":24,"tag":41,"props":3642,"children":3643},{},[3644],{"type":29,"value":3645},"\"How do I stop people using DeepSeek?\"",{"type":24,"tag":111,"props":3647,"children":3648},{},[3649,3659],{"type":24,"tag":115,"props":3650,"children":3651},{},[3652,3657],{"type":24,"tag":97,"props":3653,"children":3654},{},[3655],{"type":29,"value":3656},"First run:",{"type":29,"value":3658}," it opened P-PROVIDERS' page but couldn't point at anything, because the page had no IDs.",{"type":24,"tag":115,"props":3660,"children":3661},{},[3662,3667,3669,3674],{"type":24,"tag":97,"props":3663,"children":3664},{},[3665],{"type":29,"value":3666},"After the section IDs:",{"type":29,"value":3668}," it rang ",{"type":24,"tag":97,"props":3670,"children":3671},{},[3672],{"type":29,"value":3673},"Mode",{"type":29,"value":3675},". It read the live state (Observe; 2 exceptions covering 9 of 14 people) and gave the steps: check the approved list, switch to Enforce, review the exceptions, publish. It also warned that Enforce blocks every unapproved provider, not just DeepSeek.",{"type":24,"tag":115,"props":3677,"children":3678},{},[3679,3684,3686,3691],{"type":24,"tag":41,"props":3680,"children":3681},{},[3682],{"type":29,"value":3683},"\"What's the difference between observe and enforce?\"",{"type":29,"value":3685}," It called ",{"type":24,"tag":32,"props":3687,"children":3689},{"className":3688},[],[3690],{"type":29,"value":3411},{"type":29,"value":3692}," once and answered in the product's terms, offering to show where.",{"type":24,"tag":25,"props":3694,"children":3695},{},[3696],{"type":24,"tag":97,"props":3697,"children":3698},{},[3699],{"type":29,"value":3700},"Still not known:",{"type":24,"tag":111,"props":3702,"children":3703},{},[3704,3722,3727],{"type":24,"tag":115,"props":3705,"children":3706},{},[3707,3709,3714,3715,3720],{"type":29,"value":3708},"The configuration lists themselves (which providers are approved, which paths are restricted) appear only as page text. The agent reads them through ",{"type":24,"tag":32,"props":3710,"children":3712},{"className":3711},[],[3713],{"type":29,"value":1744},{"type":29,"value":1018},{"type":24,"tag":32,"props":3716,"children":3718},{"className":3717},[],[3719],{"type":29,"value":2126},{"type":29,"value":3721},"; they aren't indexed.",{"type":24,"tag":115,"props":3723,"children":3724},{},[3725],{"type":29,"value":3726},"Findings and people aren't searchable.",{"type":24,"tag":115,"props":3728,"children":3729},{},[3730],{"type":29,"value":3731},"In qdash the knowledge would come from the API.",{"type":24,"tag":105,"props":3733,"children":3735},{"id":3734},"open",[3736],{"type":29,"value":19},{"type":24,"tag":111,"props":3738,"children":3739},{},[3740,3758,3775,3799,3809,3825,3845,3869,3879],{"type":24,"tag":115,"props":3741,"children":3742},{},[3743,3748,3750,3756],{"type":24,"tag":97,"props":3744,"children":3745},{},[3746],{"type":29,"value":3747},"An in-app chat.",{"type":29,"value":3749}," Moved to ",{"type":24,"tag":56,"props":3751,"children":3753},{"href":3752},"\u002Fcycles\u002Fdesign\u002Fc127\u002Fdoc\u002Finitial-prompt",[3754],{"type":29,"value":3755},"c127 Guide Chat",{"type":29,"value":3757},", stage 1: the same map, knowledge and walk tools, with the page running its own tools.",{"type":24,"tag":115,"props":3759,"children":3760},{},[3761,3766,3768,3773],{"type":24,"tag":97,"props":3762,"children":3763},{},[3764],{"type":29,"value":3765},"Agent narration on screen.",{"type":29,"value":3767}," Should the agent's words appear in the panel, replacing or added to the step's own text, or stay in the harness's chat? The rules above keep them in chat, and the panel shows only who is driving. The unscripted guide proposes one exception: ",{"type":24,"tag":32,"props":3769,"children":3771},{"className":3770},[],[3772],{"type":29,"value":1744},{"type":29,"value":3774},"'s title and one sentence.",{"type":24,"tag":115,"props":3776,"children":3777},{},[3778,3783,3785,3790,3792,3797],{"type":24,"tag":97,"props":3779,"children":3780},{},[3781],{"type":29,"value":3782},"Ad-hoc tours.",{"type":29,"value":3784}," Should an agent be able to compose its own path from IDs (",{"type":24,"tag":32,"props":3786,"children":3788},{"className":3787},[],[3789],{"type":29,"value":628},{"type":29,"value":3791}," plus navigation) when no tour fits the person's question? The unscripted guide above answers part of this: a short walk of rings and callouts, with no panel. Whether a longer one gets the panel (",{"type":24,"tag":32,"props":3793,"children":3795},{"className":3794},[],[3796],{"type":29,"value":2108},{"type":29,"value":3798},", with Next and Back) waits for U4.",{"type":24,"tag":115,"props":3800,"children":3801},{},[3802,3807],{"type":24,"tag":97,"props":3803,"children":3804},{},[3805],{"type":29,"value":3806},"Where the map comes from.",{"type":29,"value":3808}," It could be hand-written per page (the plan above), generated from the IDs with descriptions filled in, or read from route meta in qdash. And should the help registry (Objective 1) and the map be one file from the start?",{"type":24,"tag":115,"props":3810,"children":3811},{},[3812,3817,3818,3823],{"type":24,"tag":97,"props":3813,"children":3814},{},[3815],{"type":29,"value":3816},"Numbered or single.",{"type":29,"value":226},{"type":24,"tag":32,"props":3819,"children":3821},{"className":3820},[],[3822],{"type":29,"value":1744},{"type":29,"value":3824}," replaces the last point. Should it be able to stack numbered markers instead (c125's marker overlay: \"1 here, 2 then here\")?",{"type":24,"tag":115,"props":3826,"children":3827},{},[3828,3836,3838,3843],{"type":24,"tag":1565,"props":3829,"children":3830},{},[3831],{"type":24,"tag":97,"props":3832,"children":3833},{},[3834],{"type":29,"value":3835},"The rail-then-page beat.",{"type":29,"value":3837}," Built: ",{"type":24,"tag":32,"props":3839,"children":3841},{"className":3840},[],[3842],{"type":29,"value":1951},{"type":29,"value":3844}," rings the way for 1.6 s, then navigates.",{"type":24,"tag":115,"props":3846,"children":3847},{},[3848,3860,3862,3867],{"type":24,"tag":97,"props":3849,"children":3850},{},[3851,3853,3858],{"type":29,"value":3852},"How much of a region ",{"type":24,"tag":32,"props":3854,"children":3856},{"className":3855},[],[3857],{"type":29,"value":1744},{"type":29,"value":3859}," returns.",{"type":29,"value":3861}," It's capped at 500 characters, and the install answer hit the cap. A bigger cap, or ",{"type":24,"tag":32,"props":3863,"children":3865},{"className":3864},[],[3866],{"type":29,"value":2126},{"type":29,"value":3868}," for long regions?",{"type":24,"tag":115,"props":3870,"children":3871},{},[3872,3877],{"type":24,"tag":97,"props":3873,"children":3874},{},[3875],{"type":29,"value":3876},"The map is hand-written,",{"type":29,"value":3878}," and U1 is what keeps it honest. The tours thread already changed pages under it once in its first hour.",{"type":24,"tag":115,"props":3880,"children":3881},{},[3882,3887,3889,3894,3895,3900],{"type":24,"tag":97,"props":3883,"children":3884},{},[3885],{"type":29,"value":3886},"Server-readable content.",{"type":29,"value":3888}," The text\u002FExamples split noted above. That decides whether ",{"type":24,"tag":32,"props":3890,"children":3892},{"className":3891},[],[3893],{"type":29,"value":572},{"type":29,"value":242},{"type":24,"tag":32,"props":3896,"children":3898},{"className":3897},[],[3899],{"type":29,"value":579},{"type":29,"value":3901}," work with no tab open.",{"type":24,"tag":3903,"props":3904,"children":3905},"style",{},[3906],{"type":29,"value":1620},1794599454056]