agenttwin 0.3.11 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/api.js +42 -2
- package/dist/cli.js +107 -28
- package/dist/dashboard/assets/next/static/{8DWbcYS099IMf1RzFG63k → BbTZs0rKnsmj45peSnlwJ}/_buildManifest.js +1 -1
- package/dist/dashboard/assets/next/static/chunks/1981-2ce2c5edd154524a.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/{4055.1056568a41510e92.js → 2442.9a266da6229b8ae0.js} +1 -1
- package/dist/dashboard/assets/next/static/chunks/2529.07927d0600506985.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/{8975.5be81ec8b09e3b45.js → 3454.d29ee7a49c2a4fba.js} +1 -1
- package/dist/dashboard/assets/next/static/chunks/{7772-425e96278b46f6c9.js → 3916-2698a1a3ecb8649f.js} +1 -1
- package/dist/dashboard/assets/next/static/chunks/4705-a6d249b4a5dcde26.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/4816-45f42396ec2135cc.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/48a1527b.6d52e40c5e62d9d5.js +2 -0
- package/dist/dashboard/assets/next/static/chunks/{6751.613adb085c9a5b06.js → 5490.0d5d8d5ea3577f20.js} +1 -1
- package/dist/dashboard/assets/next/static/chunks/650-3092bf29ff938e12.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/6f3ce29d-af1469ba72f5d3e4.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/{9013.0f2be1cc70029afa.js → 7280.01b3f749332bb075.js} +2 -2
- package/dist/dashboard/assets/next/static/chunks/794.a624e6be9e42a62b.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/_not-found/page-471a6c74344187f9.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/account/password/page-aaee6711085b485d.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/dashboard/layout-09cb13657f62384f.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/dashboard/page-945c916b24f48675.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/demo/page-3cba0aab460c8677.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/docs/[[...slug]]/page-9f7b8dca8b973b15.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/enterprise/page-4986698442bddc6b.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/layout-09868e53e4f0541f.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/login/page-2e29d4b17645c34c.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/onboarding/page-af2c4768dc34ec92.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/page-507229409812cedd.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/pricing/{page-757fd3f59cd253fb.js → page-c27282cd7bfb0fcf.js} +1 -1
- package/dist/dashboard/assets/next/static/chunks/app/signup/page-2e29d4b17645c34c.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/sitemap.xml/route-36bcc482b50fcb46.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/dashboard/layout-77a57cd622171076.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/dashboard/page-df34bcef0394d10d.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/layout-d1d715b5b2dae3cd.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/login/page-4f60d050bf954194.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/onboarding/page-abfe2f36213848d7.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/page-df6a34eff716d18e.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/app/v2/signup/page-4f60d050bf954194.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/framework-cb37e134fe056fa5.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/main-app-c83f3671ad6b824a.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/main-b7d6352ee94d0dba.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/pages/_app-9dd167be58cf5cbd.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/pages/_error-5a8b1eb076dd7c95.js +1 -0
- package/dist/dashboard/assets/next/static/chunks/webpack-44457f45df749a89.js +1 -0
- package/dist/dashboard/assets/next/static/css/0856ee8c880d8b92.css +1 -0
- package/dist/dashboard/assets/next/static/css/0cf03e33b963e5cb.css +1 -0
- package/dist/dashboard/assets/next/static/css/11f70fd04660da57.css +1 -0
- package/dist/dashboard/assets/next/static/css/14ef6d1b7f922ef2.css +1 -0
- package/dist/dashboard/assets/next/static/css/27bc5d721d729e4d.css +1 -0
- package/dist/dashboard/assets/next/static/css/{d99eecb7633d1200.css → 3f585d63d4bf0043.css} +1 -1
- package/dist/dashboard/assets/next/static/css/5d8899aaed08d7f2.css +1 -0
- package/dist/dashboard/assets/next/static/css/6b8edde77e493a51.css +1 -0
- package/dist/dashboard/assets/next/static/css/{32d869ddee6d2dc1.css → 766bc384d3febae4.css} +1 -1
- package/dist/dashboard/assets/next/static/css/81a1668ab34a36e8.css +1 -0
- package/dist/dashboard/assets/next/static/css/b15fa8a0e168d625.css +1 -0
- package/dist/dashboard/assets/next/static/css/d5d08788c3435fdf.css +1 -0
- package/dist/dashboard/assets/next/static/css/dd3fb06005e18149.css +1 -0
- package/dist/dashboard/assets/next/static/css/eea0966f05042bde.css +1 -0
- package/dist/dashboard/assets/next/static/css/f14e187b236cb6fb.css +1 -0
- package/dist/dashboard/assets/next/static/css/f57206a163d6b5be.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/gateway.js +42 -2
- package/package.json +1 -1
- package/dist/dashboard/assets/next/static/chunks/1255-b815b974120825e7.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/1848-a6938ad74a8e409f.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/3050-a8f395e3fe36d7b9.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/4343.023a18f52318dbad.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/4542.0327d0da1c3ea200.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/4bd1b696-f785427dddbba9fb.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/6787-6a8909259d0ac26c.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/_not-found/page-43db8aef3fa81958.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/account/password/page-c2ce3c796c817ca1.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/dashboard/layout-28ee3093f86fc075.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/dashboard/page-91a2efe02bd25700.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/demo/page-4dc63755e0013e7c.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/docs/[[...slug]]/page-db473994608d5c77.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/enterprise/page-9a33a4aec43377e0.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/layout-dd5d4772c11d4cbb.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/login/page-d6d4276397724d29.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/onboarding/page-1b066c493c248f29.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/page-950c663fd42544c0.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/signup/page-d6d4276397724d29.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/sitemap.xml/route-83b9d0f0ad5575d4.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/dashboard/layout-a5cf565e017886d3.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/dashboard/page-eb63255bc8df6433.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/layout-abbd9f3b8811f559.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/login/page-4f4a342a4c28f9de.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/onboarding/page-f04c0b236abaead3.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/page-cf8af0afd0589c71.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/app/v2/signup/page-4f4a342a4c28f9de.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/framework-e54b663a2888b5de.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/main-app-1ec13ceef4a34729.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/main-d1fa84e2f669be1c.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/pages/_app-6c8c2371b16a04b8.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/pages/_error-94812ad32cad7365.js +0 -1
- package/dist/dashboard/assets/next/static/chunks/webpack-60f6502c44ed95af.js +0 -1
- package/dist/dashboard/assets/next/static/css/138b575a572b2958.css +0 -1
- package/dist/dashboard/assets/next/static/css/1f0bd0855bbd1a14.css +0 -1
- package/dist/dashboard/assets/next/static/css/311920319a51fc90.css +0 -1
- package/dist/dashboard/assets/next/static/css/3f003235629d65a0.css +0 -1
- package/dist/dashboard/assets/next/static/css/448fc71b62e29403.css +0 -1
- package/dist/dashboard/assets/next/static/css/45513ebc8c6ae800.css +0 -1
- package/dist/dashboard/assets/next/static/css/4fa51ab33fbc7e1b.css +0 -1
- package/dist/dashboard/assets/next/static/css/61ec74d503f353d4.css +0 -1
- package/dist/dashboard/assets/next/static/css/807e07644631d8e2.css +0 -1
- package/dist/dashboard/assets/next/static/css/97d686ac80c4018f.css +0 -1
- package/dist/dashboard/assets/next/static/css/c1117da59daa6ba9.css +0 -1
- package/dist/dashboard/assets/next/static/css/c5ac36ef5726e746.css +0 -1
- package/dist/dashboard/assets/next/static/css/ec9722ff890f136c.css +0 -1
- package/dist/dashboard/assets/next/static/css/f9c2780fff15fd22.css +0 -1
- /package/dist/dashboard/assets/next/static/{8DWbcYS099IMf1RzFG63k → BbTZs0rKnsmj45peSnlwJ}/_ssgManifest.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9436],{3241:()=>{},3413:(e,t,a)=>{"use strict";a.d(t,{default:()=>o});var s=a(5155),n=a(2115);function o(){return(0,n.useEffect)(()=>{let e=!1;return queueMicrotask(()=>{e||function(){var e;let t=e=>document.querySelector(e),a=["Connect production","Create replica","Run code","Introduce failures","Diagnose, fix, rerun"],s=["Connect","Create replica","Run code","Add failures","Diagnose & rerun"],n=e=>[{id:"perm",name:"Expired permissions",desc:"The ".concat(e.permTool," connection loses ").concat(e.perm," write permission."),code:"403 \xb7 access denied",failCount:0,passCount:0,failure:{t:"".concat(e.action," failure swallowed"),d:"The caller received no actionable permission error."},recovery:{t:"Permission failure surfaced",d:"Workflow stops with an actionable error and no partial ".concat(e.noun," records.")}},{id:"down",name:"Service unavailable",desc:"".concat(e.downTool," is unavailable after the ").concat(e.noun," succeeds."),code:"503 \xb7 ".concat(String(e.downTool).toLowerCase()," unavailable"),failCount:1,passCount:1,failure:{t:"".concat(e.action," saved; ").concat(e.follow," lost"),d:"".concat(e.stateLabel," was written, but ").concat(e.follow," never happened.")},recovery:{t:"Outage handled",d:"".concat(e.action," preserved; ").concat(e.follow," queued for recovery.")}},{id:"late",name:"Delayed event",desc:"A completion event arrives after the caller times out.",code:"+30s \xb7 event delivery",failCount:1,passCount:1,failure:{t:"Late event overwrote newer state",d:"The expired operation updated a completed ".concat(e.noun,".")},recovery:{t:"Stale event ignored",d:"The event version check prevents a stale state transition."}},{id:"timeout",name:"Timeout after success",desc:"The operation completes, but its response is lost.",code:"ETIMEDOUT \xb7 after write",failCount:2,passCount:1,failure:{t:"Retry created a second ".concat(e.noun),d:"The original write succeeded; the retry used a new operation key."},recovery:{t:"Retry reused the operation key",d:"The existing operation is returned; no duplicate is created."}},{id:"dup",name:"Duplicate delivery",desc:"The same request or event is delivered twice.",code:"2\xd7 \xb7 same operation",failCount:2,passCount:1,failure:{t:"Duplicate processed twice",d:"No atomic deduplication guarded the repeated operation."},recovery:{t:"Duplicate safely ignored",d:"The atomic deduplication guard permits one ".concat(e.noun," state mutation.")}},{id:"rate",name:"Rate limit",desc:"".concat(e.rateTool," rejects the burst."),code:"429 \xb7 retry after ".concat(e.after),failCount:1,passCount:1,failure:{t:"".concat(e.action," dropped without retry"),d:"The retry-after interval was ignored."},recovery:{t:"Retry-after respected",d:"The simulated scheduler retries after the required delay."}}],o=(e,t,a,s,n,o,r)=>({brand:e,icon:t,sub:a,name:s,mode:n,kind:o,boundary:r}),r=[{id:"support",logo:"co-pylon.png",company:"Pylon",tag:"B2B support agent",badge:"SUPPORT",name:"pylon-support-twin",blurb:"A B2B SaaS company runs support through an agent: look up the account, decide the credit, file the engineering escalation, and answer the customer once. The stack below is the one a team like this actually runs.",caution:"The tool stack and the workflows under test are modelled for this demo. Pylon is a prospect, not an AgentTwin customer. This does not represent Pylon private architecture or a reported failure.",links:[{label:"AI support agents",href:"https://www.usepylon.com/ai-agents/support"},{label:"Slack agent",href:"https://www.usepylon.com/ai-agents/slack"}],services:[o("Slack","#","Threads \xb7 replies","Customer conversation","Simulated","amber","Thread state only; no real delivery"),o("HubSpot","H","Accounts \xb7 plans","Account and plan state","Simulated","amber","Synthetic accounts and plan data"),o("Stripe","$","Billing \xb7 credits","Billing state","Simulated","amber","Synthetic charges and credits; no money movement"),o("Linear","L","Issues \xb7 escalations","Engineering escalation","Simulated","amber","Synthetic issues; nothing filed"),o("Gmail","M","Email \xb7 replies","Email channel","Simulated","amber","Message state only; no real mail"),o("Notion","N","Runbooks \xb7 macros","Agent knowledge","Seeded fixture","","Invented macros and escalation runbooks"),o("GitHub","G","Repros \xb7 linked bugs","Bug reproduction","Sanitized copy","","Synthetic repositories and issue links"),o("Datadog","D","Service health","Dependency health","Simulated","amber","Synthetic monitors; no live telemetry"),o("Okta","O","SSO \xb7 roles","Identity and roles","Sanitized copy","","Synthetic users and role grants")],runs:[{id:"credit",label:"Issue billing credit \xb7 account #8841",entry:"issueBillingCredit()",testFile:"tests/issue-billing-credit.ts",startTitle:"Credit requested",startEvent:"issueBillingCredit() \xb7 over-billed account \xb7 #8841",settled:"One credit recorded; customer notified once.",stateKey:"stripe.credits",faults:n({permTool:"HubSpot",downTool:"Slack",perm:"billing",action:"Credit",noun:"credit",follow:"customer reply",stateLabel:"Credit state",rateTool:"Linear",after:"10s"})},{id:"escalation",label:"Escalate P1 \xb7 SLA at risk \xb7 ticket #4412",entry:"escalateToEngineering()",testFile:"tests/escalate-p1.ts",startTitle:"Escalation opened",startEvent:"escalateToEngineering() \xb7 P1 \xb7 ticket #4412",settled:"One issue created; the on-call engineer paged once.",stateKey:"linear.escalations",faults:n({permTool:"Linear",downTool:"Slack",perm:"issue-create",action:"Escalation",noun:"escalation",follow:"on-call page",stateLabel:"Escalation state",rateTool:"Linear",after:"15s"})},{id:"summary",label:"Summarize 40-message thread \xb7 enterprise account",entry:"draftResolutionSummary()",testFile:"tests/draft-summary.ts",startTitle:"Summary requested",startEvent:"draftResolutionSummary() \xb7 40 messages \xb7 acct-119",settled:"One summary stored; nothing sent to the customer.",stateKey:"pylon.summaries",faults:n({permTool:"Notion",downTool:"Slack",perm:"write",action:"Summary",noun:"summary",follow:"Slack digest",stateLabel:"Summary state",rateTool:"Datadog",after:"30s"})}]},{id:"ecom",logo:"co-intercom.svg",company:"Intercom",tag:"E-commerce support agent",badge:"SUPPORT",name:"intercom-returns-twin",blurb:"A Shopify brand lets a support agent resolve post-purchase conversations: find the order, approve the return or exchange, process the refund, and message the shopper in the brand voice.",caution:"The tool stack and the workflows under test are modelled for this demo. Intercom is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Fin AI agent",href:"https://www.intercom.com/fin"},{label:"Intercom AI",href:"https://www.intercom.com/ai"}],services:[o("Shopify","S","Orders \xb7 returns","Order state","Simulated","amber","Synthetic orders and returns; no money movement"),o("Intercom","I","Inbox \xb7 Fin replies","Support conversation","Simulated","amber","Ticket state and replies; no customer contact"),o("Stripe","$","Refunds \xb7 charges","Payment state","Simulated","amber","Synthetic refunds; no money movement"),o("Klaviyo","K","Email \xb7 SMS flows","Shopper notification","Simulated","amber","Message state only; no real delivery"),o("Slack","#","Internal escalation","Internal handoff","Simulated","amber","Channel state only; no real messages"),o("Notion","N","Macros \xb7 policy","Support knowledge","Seeded fixture","","Invented macros and exchange rules"),o("Gmail","M","Email fallback","Email channel","Simulated","amber","Message state only; no real mail"),o("Postgres","Pg","Orders \xb7 customers","Order store","Sanitized copy","","Synthetic orders, no production rows")],runs:[{id:"return",label:"Resolve post-purchase return \xb7 order #2210",entry:"resolveReturnRequest()",testFile:"tests/resolve-return.ts",startTitle:"Return requested",startEvent:"resolveReturnRequest() \xb7 exchange requested \xb7 order #2210",settled:"One return created; shopper notified once.",stateKey:"shopify.returns",faults:n({permTool:"Shopify",downTool:"Klaviyo",perm:"returns",action:"Return",noun:"return",follow:"shopper notification",stateLabel:"Return state",rateTool:"Klaviyo",after:"30s"})},{id:"address",label:"Change delivery address \xb7 order #88231",entry:"changeDeliveryAddress()",testFile:"tests/change-address.ts",startTitle:"Address change requested",startEvent:"changeDeliveryAddress() \xb7 order #88231 \xb7 pre-fulfilment",settled:"One order updated; fulfilment notified once.",stateKey:"shopify.orders",faults:n({permTool:"Shopify",downTool:"Slack",perm:"orders",action:"Address",noun:"address change",follow:"fulfilment notice",stateLabel:"Order state",rateTool:"Shopify",after:"20s"})},{id:"refund",label:"Refund damaged item \xb7 order #40117",entry:"issueRefund()",testFile:"tests/issue-refund.ts",startTitle:"Refund requested",startEvent:"issueRefund() \xb7 damaged item \xb7 order #40117",settled:"One refund issued; shopper receipt sent once.",stateKey:"stripe.refunds",faults:n({permTool:"Stripe",downTool:"Klaviyo",perm:"refunds",action:"Refund",noun:"refund",follow:"shopper receipt",stateLabel:"Refund state",rateTool:"Stripe",after:"60s"})}]},{id:"finance",logo:"co-ramp.png",company:"Ramp",tag:"Accounts payable agent",badge:"FINANCE",name:"ramp-ap-twin",blurb:"A finance team runs an AP agent: read the vendor invoice out of the inbox, code the line items against the ledger, check for duplicates, route the approval, and schedule the payment.",caution:"The tool stack and the workflows under test are modelled for this demo. Ramp is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Accounts payable",href:"https://ramp.com/accounts-payable"},{label:"Agents for AP",href:"https://ramp.com/blog/ramp-ap-agents-announcement"}],services:[o("Gmail","M","Invoices \xb7 inbox","Invoice intake","Simulated","amber","Synthetic invoices; no real mail"),o("NetSuite","N","ERP \xb7 ledger","General ledger","Sanitized copy","","Synthetic chart of accounts; no production import"),o("Slack","#","Approvals \xb7 alerts","Approval routing","Simulated","amber","Approval state; no real messages"),o("Bank rail","B","ACH \xb7 wires","Payment rail","Simulated","amber","Payment state only; no money movement"),o("Snowflake","Sf","Spend analytics","Spend warehouse","Sanitized copy","","Synthetic spend rows; no production data"),o("Postgres","Pg","Bills \xb7 vendors","Bill store","Sanitized copy","","Synthetic bills and vendors"),o("Okta","O","Roles \xb7 limits","Approval authority","Sanitized copy","","Synthetic roles and approval thresholds"),o("Calendar","C","Close calendar","Close schedule","Seeded fixture","","Invented close dates and reminders")],runs:[{id:"invoice",label:"Process vendor invoice \xb7 INV-40981",entry:"processInvoice()",testFile:"tests/process-invoice.ts",startTitle:"Invoice received",startEvent:"processInvoice() \xb7 invoice INV-40981 \xb7 18,400 USD",settled:"One invoice coded, approved, and scheduled once.",stateKey:"erp.bills",faults:n({permTool:"NetSuite",downTool:"Slack",perm:"bill-posting",action:"Invoice",noun:"invoice",follow:"approval request",stateLabel:"Bill state",rateTool:"Bank rail",after:"60s"})},{id:"approval",label:"Approval escalation \xb7 bill #7712 over threshold",entry:"routeApproval()",testFile:"tests/route-approval.ts",startTitle:"Approval needed",startEvent:"routeApproval() \xb7 42,000 USD \xb7 threshold 25,000",settled:"One approval routed; the bill held once.",stateKey:"erp.approvals",faults:n({permTool:"Okta",downTool:"Slack",perm:"approve",action:"Approval",noun:"approval",follow:"approver page",stateLabel:"Approval state",rateTool:"Slack",after:"20s"})},{id:"vendor",label:"Duplicate vendor onboarding \xb7 ACME Corp",entry:"detectDuplicateVendor()",testFile:"tests/dedupe-vendor.ts",startTitle:"Vendor submitted",startEvent:"detectDuplicateVendor() \xb7 ACME Corp \xb7 tax ID match",settled:"One vendor kept; the duplicate merged once.",stateKey:"erp.vendors",faults:n({permTool:"NetSuite",downTool:"Gmail",perm:"vendor-create",action:"Vendor",noun:"vendor record",follow:"welcome email",stateLabel:"Vendor state",rateTool:"Snowflake",after:"30s"})}]},{id:"gtm",logo:"co-clay.png",company:"Clay",tag:"GTM agent",badge:"GTM",name:"clay-gtm-twin",blurb:"A revenue team runs an agent that enriches each inbound lead, scores it against the ICP, routes it to the right rep, and writes the result back to the CRM without duplicating records.",caution:"The tool stack and the workflows under test are modelled for this demo. Clay is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Claygent",href:"https://www.clay.com/claygent"},{label:"Clay",href:"https://www.clay.com/"}],services:[o("Salesforce","Sf","Leads \xb7 owners","CRM system of record","Simulated","amber","Synthetic leads and ownership; no production writes"),o("HubSpot","H","Lifecycle \xb7 staging","Marketing CRM","Simulated","amber","Synthetic lifecycle stages"),o("Slack","#","Rep alerts","Routing notifications","Simulated","amber","Message state only; no real messages"),o("Gmail","M","Sequences \xb7 replies","Outbound channel","Simulated","amber","Message state only; no real mail"),o("Postgres","Pg","Enrichment store","Enrichment cache","Sanitized copy","","Synthetic enrichment rows"),o("Snowflake","Sf","Warehouse sync","Analytics warehouse","Sanitized copy","","Synthetic rows; no production export"),o("Mixpanel","Mx","Product signals","Usage signals","Simulated","amber","Synthetic event counts"),o("Notion","N","ICP \xb7 playbooks","GTM knowledge","Seeded fixture","","Invented ICP definitions and playbooks"),o("Calendar","C","Meeting booking","Scheduling","Seeded fixture","","Synthetic availability; no bookings")],runs:[{id:"enrich",label:"Enrich inbound lead \xb7 acme.io",entry:"enrichAndScore()",testFile:"tests/enrich-lead.ts",startTitle:"Lead submitted",startEvent:"enrichAndScore() \xb7 acme.io \xb7 inbound form",settled:"One enriched record scored and stored once.",stateKey:"crm.leads",faults:n({permTool:"Salesforce",downTool:"Slack",perm:"lead-write",action:"Lead",noun:"lead",follow:"rep alert",stateLabel:"Lead state",rateTool:"Snowflake",after:"30s"})},{id:"route",label:"Round-robin routing \xb7 14 leads \xb7 3 territories",entry:"routeToRep()",testFile:"tests/route-leads.ts",startTitle:"Routing batch started",startEvent:"routeToRep() \xb7 14 leads \xb7 3 territories",settled:"One owner assigned per lead; no double assignment.",stateKey:"crm.assignments",faults:n({permTool:"Salesforce",downTool:"Slack",perm:"assignment",action:"Assignment",noun:"assignment",follow:"rep DM",stateLabel:"Assignment state",rateTool:"Salesforce",after:"15s"})},{id:"sync",label:"Write enrichment back to CRM \xb7 320 records",entry:"syncEnrichment()",testFile:"tests/sync-enrichment.ts",startTitle:"Sync started",startEvent:"syncEnrichment() \xb7 320 records \xb7 nightly job",settled:"One sync completed; every record written once.",stateKey:"crm.records",faults:n({permTool:"HubSpot",downTool:"Snowflake",perm:"record-update",action:"Record",noun:"record",follow:"warehouse sync",stateLabel:"Record state",rateTool:"HubSpot",after:"60s"})}]},{id:"coding",logo:"co-cognition.png",company:"Cognition",tag:"Coding agent",badge:"ENGINEERING",name:"cognition-coding-twin",blurb:"An engineering team lets a coding agent pick up tickets: reproduce the failure, write the patch, run the migration, and roll back the release when the checks disagree.",caution:"The tool stack and the workflows under test are modelled for this demo. Cognition is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Devin",href:"https://cognition.ai/"},{label:"Platform",href:"https://cognition.ai/platform"}],services:[o("GitHub","G","PRs \xb7 checks","Source control","Simulated","amber","Synthetic branches and checks; nothing pushed"),o("npm registry","Npm","Packages \xb7 deps","Dependency source","Read only","gray","Read-only package metadata"),o("AWS EC2","A","Compute \xb7 deploys","Runtime infrastructure","Simulated","amber","No instances provisioned or changed"),o("Terraform","Tf","Plans \xb7 state","Infrastructure definition","Read only","gray","Plans read and evaluated only"),o("Postgres","Pg","Schema \xb7 rows","Application database","Sanitized copy","","Synthetic rows; migrations evaluated offline"),o("Datadog","D","Metrics \xb7 traces","Service telemetry","Simulated","amber","Synthetic metrics; no live telemetry"),o("PagerDuty","Pd","Escalations","Incident escalation","Simulated","amber","No real pages sent"),o("Slack","#","PR \xb7 deploy notices","Team notifications","Simulated","amber","Message state only; no real messages"),o("Linear","L","Issues \xb7 intake","Issue tracker","Simulated","amber","Synthetic issues; nothing filed")],runs:[{id:"ci",label:"Fix failing CI on main \xb7 PR #1842",entry:"resolveIssue()",testFile:"tests/resolve-issue.ts",startTitle:"Check failure observed",startEvent:"resolveIssue() \xb7 PR #1842 \xb7 3 failing jobs",settled:"One patch pushed; the checks turned green once.",stateKey:"gh.check_runs",faults:n({permTool:"GitHub",downTool:"Slack",perm:"checks:write",action:"Patch",noun:"patch",follow:"review request",stateLabel:"Check state",rateTool:"GitHub",after:"30s"})},{id:"migrate",label:"Migrate users table \xb7 12,340 rows",entry:"migrateSchema()",testFile:"tests/migrate-users.ts",startTitle:"Migration started",startEvent:"migrateSchema() \xb7 users \xb7 12,340 rows \xb7 2 steps",settled:"One migration recorded; every row migrated once.",stateKey:"db.migrations",faults:n({permTool:"Postgres",downTool:"Slack",perm:"ddl-write",action:"Migration",noun:"migration",follow:"status message",stateLabel:"Migration state",rateTool:"Postgres",after:"45s"})},{id:"rollback",label:"Roll back bad deploy \xb7 svc-api release 4.18.2",entry:"rollBackDeploy()",testFile:"tests/rollback-deploy.ts",startTitle:"Rollback requested",startEvent:"rollBackDeploy() \xb7 svc-api \xb7 release 4.18.2",settled:"One release rolled back; traffic restored once.",stateKey:"deploy.releases",faults:n({permTool:"AWS EC2",downTool:"PagerDuty",perm:"deploy:write",action:"Rollback",noun:"rollback",follow:"incident note",stateLabel:"Release state",rateTool:"Datadog",after:"20s"})}]},{id:"oncall",logo:"co-sentry.svg",company:"Sentry",tag:"On-call agent",badge:"ON-CALL",name:"sentry-oncall-twin",blurb:"An on-call agent watches the error stream: group the new issue, open the incident, page the right responder, and write the root cause summary once the error rate settles.",caution:"The tool stack and the workflows under test are modelled for this demo. Sentry is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Sentry platform",href:"https://sentry.io/platform/"},{label:"Sentry",href:"https://sentry.io/"}],services:[o("PagerDuty","Pd","Rotations \xb7 pages","On-call paging","Simulated","amber","No real pages sent"),o("Slack","#","Incident channel","Incident comms","Simulated","amber","Channel state only; no real messages"),o("GitHub","G","Fix PRs","Remediation code","Simulated","amber","Synthetic PRs; nothing pushed"),o("Linear","L","Follow-up issues","Follow-up tracking","Simulated","amber","Synthetic issues; nothing filed"),o("Datadog","D","Correlated metrics","Correlated telemetry","Simulated","amber","Synthetic metrics; no live telemetry"),o("AWS EC2","A","Hosted services","Service inventory","Sanitized copy","","No instances provisioned or changed"),o("Terraform","Tf","Service definitions","Service registry","Read only","gray","Read-only service definitions"),o("Okta","O","Identity context","User identity","Sanitized copy","","Synthetic users and groups"),o("Postgres","Pg","Event store","Event archive","Sanitized copy","","Synthetic events; no production rows")],runs:[{id:"triage",label:"Triage new issue \xb7 checkout-api",entry:"triageAlert()",testFile:"tests/triage-issue.ts",startTitle:"Issue seen",startEvent:"triageAlert() \xb7 checkout-api \xb7 1,204 events",settled:"One triage posted; the assignee notified once.",stateKey:"issues.groups",faults:n({permTool:"Linear",downTool:"Slack",perm:"issue-create",action:"Triage",noun:"triage",follow:"assignee notice",stateLabel:"Triage state",rateTool:"Slack",after:"20s"})},{id:"incident",label:"Page on-call \xb7 error spike 5x baseline",entry:"openIncident()",testFile:"tests/open-incident.ts",startTitle:"Spike detected",startEvent:"openIncident() \xb7 5x baseline \xb7 3 minute window",settled:"One incident opened; on-call paged once.",stateKey:"incidents.active",faults:n({permTool:"PagerDuty",downTool:"Slack",perm:"incident-write",action:"Incident",noun:"incident",follow:"on-call page",stateLabel:"Incident state",rateTool:"PagerDuty",after:"60s"})},{id:"rca",label:"Root cause summary \xb7 47 events after resolution",entry:"summarizeRootCause()",testFile:"tests/rca-summary.ts",startTitle:"Resolution observed",startEvent:"summarizeRootCause() \xb7 47 events \xb7 12 minutes",settled:"One RCA stored; stakeholders notified once.",stateKey:"rca.reports",faults:n({permTool:"Postgres",downTool:"Slack",perm:"rca-write",action:"RCA",noun:"RCA",follow:"stakeholder summary",stateLabel:"RCA state",rateTool:"Datadog",after:"30s"})}]},{id:"healthcare",logo:"co-abridge.png",company:"Abridge",tag:"Clinical documentation agent",badge:"HEALTHCARE",name:"abridge-clinical-twin",blurb:"A health system runs a documentation agent: draft the encounter note from the visit, apply coding flags for review, and reconcile the orders against the medication list before sign-off.",caution:"The tool stack and the workflows under test are modelled for this demo. Abridge is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Abridge",href:"https://abridge.com/"},{label:"For clinicians",href:"https://abridge.com/clinicians"}],services:[o("EHR","Eh","Encounters \xb7 orders","Source of truth","Sanitized copy","","Synthetic encounters; no production patient data"),o("Clinical notes","Cn","Drafts \xb7 sign-off","Note drafts","Seeded fixture","","Invented note content awaiting sign-off"),o("Coding rules","Cr","ICD-10 \xb7 CPT","Coding reference","Seeded fixture","","Invented coding hints, clinician review required"),o("Slack","#","Care-team review","Care-team handoff","Simulated","amber","Message state only; no real messages"),o("Gmail","M","Patient follow-up","Follow-up channel","Simulated","amber","Message state only; no real mail"),o("Postgres","Pg","Normalized store","Normalized records","Sanitized copy","","Synthetic records; no production rows"),o("Okta","O","Clinician roles","Access control","Sanitized copy","","Synthetic users and clinical roles"),o("Calendar","C","Scheduling","Visit schedule","Seeded fixture","","Synthetic appointments; no bookings")],runs:[{id:"note",label:"Draft encounter note \xb7 visit #8821",entry:"fileEncounterNote()",testFile:"tests/file-note.ts",startTitle:"Visit closed",startEvent:"fileEncounterNote() \xb7 visit #8821 \xb7 18 minute audio",settled:"One note drafted; clinician sign-off requested once.",stateKey:"ehr.notes",faults:n({permTool:"EHR",downTool:"Slack",perm:"note-write",action:"Note",noun:"note",follow:"clinician review request",stateLabel:"Note state",rateTool:"EHR",after:"45s"})},{id:"coding",label:"Apply coding flags \xb7 12 claims for review",entry:"flagCoding()",testFile:"tests/flag-coding.ts",startTitle:"Claims batch opened",startEvent:"flagCoding() \xb7 12 claims \xb7 ICD-10 and CPT",settled:"One flag set applied; each claim flagged once.",stateKey:"ehr.codes",faults:n({permTool:"Coding rules",downTool:"Slack",perm:"code-apply",action:"Flag",noun:"coding flag",follow:"review queue notice",stateLabel:"Flag state",rateTool:"EHR",after:"30s"})},{id:"reconcile",label:"Reconcile orders vs medications \xb7 9 orders",entry:"reconcileOrders()",testFile:"tests/reconcile-orders.ts",startTitle:"Reconciliation started",startEvent:"reconcileOrders() \xb7 9 orders \xb7 3 mismatches",settled:"One reconciliation recorded; each mismatch resolved once.",stateKey:"ehr.orders",faults:n({permTool:"EHR",downTool:"Gmail",perm:"order-write",action:"Reconciliation",noun:"reconciliation",follow:"pharmacy message",stateLabel:"Order state",rateTool:"Postgres",after:"60s"})}]},{id:"security",logo:"co-paloalto.png",company:"Palo Alto Networks",tag:"Security triage agent",badge:"SECURITY",name:"paloalto-triage-twin",blurb:"A security operations team runs a triage agent: open the case from the SIEM alert, correlate the surrounding events, isolate the affected host, and hand the responder a complete picture.",caution:"The tool stack and the workflows under test are modelled for this demo. Palo Alto Networks is a prospect, not an AgentTwin customer. This does not represent their product architecture or a reported failure.",links:[{label:"Cortex",href:"https://www.paloaltonetworks.com/cortex"},{label:"Cortex XDR",href:"https://www.paloaltonetworks.com/cortex/cortex-xdr"}],services:[o("SIEM","Si","Alerts \xb7 detections","Alert intake","Simulated","amber","Synthetic alerts; no production events"),o("EDR","Ed","Endpoints \xb7 isolation","Endpoint control","Simulated","amber","No hosts touched or isolated"),o("PagerDuty","Pd","Responder paging","Responder paging","Simulated","amber","No real pages sent"),o("Slack","#","Triage channel","Analyst comms","Simulated","amber","Channel state only; no real messages"),o("GitHub","G","Detection rules","Detection content","Read only","gray","Read-only rule definitions"),o("AWS EC2","A","Workload inventory","Workload inventory","Sanitized copy","","No instances provisioned or changed"),o("Terraform","Tf","Fleet definitions","Fleet definitions","Read only","gray","Read-only fleet definitions"),o("Okta","O","Identity context","Identity context","Sanitized copy","","Synthetic users and sessions"),o("Datadog","D","Telemetry","Correlated telemetry","Simulated","amber","Synthetic metrics; no live telemetry")],runs:[{id:"alert",label:"Triage endpoint alert \xb7 host web-14",entry:"triageAlert()",testFile:"tests/triage-alert.ts",startTitle:"Alert raised",startEvent:"triageAlert() \xb7 host web-14 \xb7 severity high",settled:"One case opened; the responder notified once.",stateKey:"siem.cases",faults:n({permTool:"EDR",downTool:"Slack",perm:"case-write",action:"Case",noun:"case",follow:"responder notice",stateLabel:"Case state",rateTool:"Datadog",after:"30s"})},{id:"correlate",label:"Correlate 5 events \xb7 suspicious egress",entry:"correlateEvents()",testFile:"tests/correlate-events.ts",startTitle:"Events ingested",startEvent:"correlateEvents() \xb7 5 events \xb7 40 minute window",settled:"One correlation stored; each event linked once.",stateKey:"siem.correlations",faults:n({permTool:"SIEM",downTool:"Slack",perm:"correlation-write",action:"Correlation",noun:"correlation",follow:"analyst digest",stateLabel:"Correlation state",rateTool:"SIEM",after:"45s"})},{id:"isolate",label:"Isolate compromised host \xb7 laptop-207",entry:"isolateHost()",testFile:"tests/isolate-host.ts",startTitle:"Isolation requested",startEvent:"isolateHost() \xb7 laptop-207 \xb7 EDR policy",settled:"One host isolated; the ticket closed once.",stateKey:"edr.isolations",faults:n({permTool:"EDR",downTool:"PagerDuty",perm:"isolation",action:"Isolation",noun:"isolation",follow:"ticket update",stateLabel:"Isolation state",rateTool:"PagerDuty",after:"60s"})}]}],i={step:0,connected:!1,replica:!1,busy:!1,customer:"support",mask:!0,isolated:!0,faults:[],recovery:!1,runs:[],tab:"timeline",notice:"",name:r[0].name,runId:r[0].runs[0].id},c=()=>r.find(e=>e.id===i.customer),l=()=>{let e=c();return e.runs.find(e=>e.id===i.runId)||e.runs[0]},d=e=>String(e).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e]),u=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return'<span class="badge '.concat(t,'">').concat(e,"</span>")},p={GitHub:"github.svg",Gmail:"gmail.svg",Slack:"slack.svg",Shopify:"shopify.svg",Intercom:"intercom.svg",Stripe:"stripe.svg",Postgres:"postgres.svg",Salesforce:"salesforce.svg",Calendar:"google-calendar.svg","npm registry":"npm.svg","AWS EC2":"aws.svg",Terraform:"terraform.svg",PagerDuty:"pagerduty.svg",HubSpot:"hubspot.svg",Linear:"linear.svg",Klaviyo:"klaviyo.png",Clay:"clay.png",NetSuite:"netsuite.png",Datadog:"datadog.svg",Okta:"okta.svg",Notion:"notion.svg",Snowflake:"snowflake.svg",Mixpanel:"mixpanel.svg","Clinical notes":"notes.svg","Coding rules":"codes.svg","Return policy":"policy.svg","Bank rail":"bank.svg","CI runner":"ci.svg",EHR:"ehr.svg",SIEM:"siem.svg",EDR:"edr.svg"},m=e=>p[e.brand]?'<img src="/prototype/dist/icons/'.concat(p[e.brand],'" alt="" aria-hidden="true">'):d(e.icon),v=(e,t)=>e.logo?'<span class="'.concat(t,'"><img src="/prototype/dist/icons/').concat(e.logo,'" alt="').concat(d(e.company),'" title="').concat(d(e.company),'"></span>'):'<span class="'.concat(t,'">').concat(d(e.company[0].toLowerCase()),"</span>"),h=function(e,t){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"primary",s=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return'<button class="btn '.concat(a,'" data-action="').concat(t,'" ').concat(s?"disabled":"",">").concat(e,"</button>")},g=function(e,t){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return'<section class="panel"><div class="panel-head"><h2>'.concat(e,"</h2><span>").concat(a,"</span></div>").concat(t,"</section>")};function f(e){return 0===e||1===e&&i.connected||e>=2&&i.replica}function y(e){t("#announcer").textContent=e}function b(e){var t;null==(t=document.querySelector(".toast"))||t.remove();let a=document.createElement("div");a.className="toast",a.textContent=e,document.body.append(a),y(e),setTimeout(()=>a.remove(),3300)}function w(e){var a;!i.busy&&f(e)&&(i.step=e,K(),null==(a=t("#step-title"))||a.focus({preventScroll:!0}))}function S(){let e=c();return'<div class="map"><div class="map-label">'.concat(i.replica?"REPLICA TOPOLOGY":"DISCOVERED TOPOLOGY",' / ILLUSTRATIVE DATA</div><div class="rootnode">').concat(v(e,"service-icon"),'<div class="node-title">').concat(d(e.company),'<div class="node-sub">').concat(i.replica?d(i.name):"production \xb7 illustrative manifest","</div></div>").concat(u(i.replica?"Isolated":"Read only",i.replica?"":"gray"),'</div><div class="services">').concat(e.services.map(e=>'<div class="service"><div class="service-icon">'.concat(m(e),'</div><div class="node-title">').concat(e.brand,'</div><div class="node-sub">').concat(e.sub,"</div>").concat(u(e.mode,e.kind),"</div>")).join(""),'</div></div><div class="map-footer"><span class="key"><i class="sq"></i> Seeded fixture</span><span class="key"><i class="sq amber"></i> Behavioral twin</span><span class="key"><i class="sq gray"></i> Untested</span></div>')}function k(){return g("Replica boundaries",'<div class="panel-body"><div class="detail-row"><span>Production writes</span><strong>Blocked</strong></div><div class="detail-row"><span>Customer data</span><strong>Masked</strong></div><div class="detail-row"><span>Credentials</span><strong>Test only</strong></div><div class="detail-row"><span>Outbound email</span><strong>Captured</strong></div><div class="callout">This prototype uses synthetic fixtures. No cloud accounts, databases, or external services are connected.</div></div>')}function T(e){let t=e.id===i.customer;return'<label class="select-card '.concat(t?"selected":"",'"><input type="radio" name="customer" value="').concat(e.id,'" ').concat(t?"checked":"",' aria-label="').concat(d(e.tag),'">').concat(v(e,"large-icon"),'<div class="content"><div class="card-top"><strong>').concat(d(e.company),"</strong>").concat(u(e.badge,"gray"),"</div><p>").concat(d(e.tag)," \xb7 ").concat(e.services.length," tools \xb7 ").concat(e.runs.length,' runs in flight</p><ul class="card-runs">').concat(e.runs.map(e=>"<li>".concat(d(e.label),"</li>")).join(""),"</ul></div></label>")}function C(){let e=c();return'<div class="grid"><div class="stacked">'.concat(g("Example customers",'<div class="panel-body"><div class="connection-header"><div class="large-icon">⌘</div><div><h2>Start with a customer.</h2><p>'.concat(r.length," real companies, each modelled with the tool stack it actually runs and ").concat(r[0].runs.length,' workflows already in twin runs. Pick one to see what AgentTwin would catch.</p></div></div><div class="customer-list">').concat(r.map(T).join(""),'</div><div class="selected-detail"><p class="aside-note">').concat(d(e.blurb),"</p>").concat(e.links.length?'<p class="aside-note" style="margin-top:10px">'.concat(e.links.map(e=>'<a href="'.concat(e.href,'" target="_blank" rel="noopener noreferrer">').concat(e.label,"</a>")).join(" \xb7 "),"</p>"):"",'<div class="callout amber">').concat(d(e.caution),'</div></div><div class="callout">An AgentTwin connector would use scoped, read-only discovery. This prototype loads an illustrative manifest — no credentials, no live systems.</div>').concat(h(i.busy?"Discovering resources…":i.connected?"Review discovered environment":"Run production discovery","discover","primary full",i.busy)).concat(i.busy?'<div class="progress"><div></div></div>':"","</div>"))," ").concat(i.connected?g("Environment discovered",S(),"".concat(e.services.length," DEPENDENCIES")):"",'</div><aside class="stacked">').concat(g("Connection checklist",'<div class="panel-body"><div class="eyebrow">01 / DISCOVERY</div><h3 class="side-title" style="margin-top:15px">Know what you depend on.</h3><p class="aside-note">Build a map before making a replica.</p>'.concat(["Application & entrypoints","Infrastructure & region","Database schema & state","External services","Configuration & permissions"].map(e=>'<div class="detail-row"><span>'.concat(e,'</span><strong class="text-green">').concat(i.connected?"✓":"—","</strong></div>")).join(""),'<div class="callout amber">A replica is only as useful as its coverage. Unverified behavior stays visible.</div></div>'))).concat(k(),"</aside></div>")}function R(){let e=c();return'<div class="grid"><div class="stacked">'.concat(g("Your environment, safely replicated",S(),"".concat(e.services.length," RESOURCES"))).concat(g("What goes into your replica",'<div class="table-scroll"><table class="resource-table"><thead><tr><th>Resource</th><th>Replica behavior</th><th>Coverage boundary</th></tr></thead><tbody>'.concat(c().services.map(e=>'<tr><td><div class="resource-name"><div class="service-icon">'.concat(m(e),"</div><div>").concat(e.brand,'<div class="secondary">').concat(e.name,"</div></div></div></td><td>").concat(u(e.mode,e.kind),'</td><td class="subtle">').concat(e.boundary,"</td></tr>")).join(""),"</tbody></table></div>")),'</div><aside class="stacked">').concat(g("Configure replica",'<div class="panel-body"><label class="label" for="replica-name" style="margin-top:0">Replica name</label><input class="field" id="replica-name" maxlength="40" value="'.concat(d(i.name),'" ').concat(i.replica?"disabled":"",'><label class="toggle-row"><input type="checkbox" checked disabled><div>Sanitize personal data<p>Replace names, emails, and identifiers.</p></div></label><label class="toggle-row"><input type="checkbox" checked disabled><div>Isolate credentials<p>Use test identities. Block production writes.</p></div></label><div class="detail-row"><span>Baseline</span><strong>snapshot_001</strong></div><div class="detail-row"><span>External behavior</span>').concat(u("Simulated","amber"),"</div>").concat(h(i.busy?"Creating replica…":i.replica?"Continue to run code":"Create test replica",i.replica?"run-page":"create","primary full",i.busy)).concat(i.busy?'<div class="progress"><div></div></div>':"",'<p class="safe-note">Prototype \xb7 no infrastructure provisioned</p></div>'))).concat(k(),"</aside></div>")}function E(){let e=c(),t=l();return'<div class="metric-grid"><div class="metric"><strong>'.concat(e.services.length,'</strong><span>Tools in the stack</span></div><div class="metric"><strong>').concat(e.runs.length,'</strong><span>Twin runs in flight</span></div><div class="metric"><strong>').concat(i.runs.length,'</strong><span>Completed test runs</span></div></div><div class="grid"><div class="stacked">').concat(g("Run against your replica",'<div class="panel-body">'.concat(function(){let e=c();return'<span class="label" style="margin-top:0">Twin runs in flight</span><div class="run-list" role="radiogroup" aria-label="Twin runs in flight">'.concat(e.runs.map(e=>{let t=e.id===i.runId,a=i.runs.filter(t=>t.runId===e.id).at(-1),s=a?u(a.pass?"PASS":"FAIL",a.pass?"":"red"):u("In flight","gray");return'<label class="run-card '.concat(t?"selected":"",'"><input type="radio" name="twinrun" value="').concat(e.id,'" ').concat(t?"checked":"",' aria-label="').concat(d(e.label),'"><span class="run-mark" aria-hidden="true">').concat(t?"●":"○",'</span><span class="run-body"><strong>').concat(d(e.label),"</strong><small>").concat(d(e.entry)," \xb7 ").concat(d(e.testFile),"</small></span>").concat(s,"</label>")}).join(""),"</div>")}(),'<div class="code"><span class="comment"># Illustrative integration command</span>\nagenttwin run ').concat(t.testFile," \\\n --world ").concat(d(i.name),' \\\n --snapshot snapshot_001</div><p class="aside-note">This demo runs a scripted workflow against in-memory state. Executing your repository code requires a connected runtime.</p><label class="toggle-row"><input id="recovery" type="checkbox" ').concat(i.recovery?"checked":"",'><div>Preview recovery fixture<p>Show a separate scripted example with safe retries, deduplication, and explicit failure handling.</p></div></label><div class="row-buttons">').concat(h(i.busy?"Running simulation…":"Run simulated workflow","run","primary",i.busy)).concat(h("Configure failures","fault-page","",i.busy),"</div>").concat(i.busy?'<div class="progress"><div></div></div>':"","</div>"))).concat(g("Recent runs",'<div class="panel-body">'.concat(i.runs.length?i.runs.slice().reverse().slice(0,4).map(e=>'<div class="history"><span style="font-family:var(--mono)">run_'.concat(String(e.id).padStart(3,"0"),'</span><span class="subtle">').concat(d(e.runLabel||"")," \xb7 ").concat(e.faults.length?e.faults.length+" conditions":"baseline"," \xb7 ").concat(e.recovery?"recovery preview":"original fixture","</span>").concat(u(e.pass?"PASS":"FAIL",e.pass?"":"red"),"</div>")).join(""):'<p class="aside-note">No runs yet. Start with a baseline, then introduce a failure.</p>',"</div>")),' </div><aside class="stacked">').concat(g("Execution context",'<div class="panel-body"><div class="detail-row"><span>Environment</span><strong>'.concat(d(i.name),'</strong></div><div class="detail-row"><span>Starting state</span><strong>snapshot_001</strong></div><div class="detail-row"><span>Entrypoint</span><strong>').concat(d(t.entry),'</strong></div><div class="detail-row"><span>Network</span><strong>Simulated</strong></div><div class="callout">Each demo run starts from the same baseline. Faults are applied only inside the replica.</div></div>'))).concat(k(),"</aside></div>")}function A(){let e=c(),t=l();return'<div class="grid"><div class="stacked">'.concat(g("Choose what breaks",'<div class="panel-body"><p class="aside-note" style="margin-bottom:6px">Twin run under test \xb7 <strong>'.concat(d(t.label),'</strong></p><p class="aside-note" style="margin-bottom:20px">Combine conditions to test how the workflow recovers.</p><div class="fault-grid">').concat(t.faults.map(e=>'<label class="fault"><div class="fault-head">'.concat(e.name,'<input type="checkbox" name="fault" value="').concat(e.id,'" ').concat(i.faults.includes(e.id)?"checked":"","></div><p>").concat(e.desc,"</p><code>").concat(e.code,"</code></label>")).join(""),'</div><div class="row-buttons">').concat(h(i.busy?"Running simulation…":"Run with selected failures","run","primary",i.busy||!i.faults.length)).concat(h("Clear selection","clear","",i.busy||!i.faults.length),"</div>").concat(i.busy?'<div class="progress"><div></div></div>':"","</div>")),'</div><aside class="stacked">').concat(g("Experiment setup",'<div class="panel-body"><div class="eyebrow">CONTROLLED CONDITIONS</div><h3 class="side-title" style="margin-top:16px">Break the replica.</h3><p class="aside-note">Keep production out of the experiment.</p><div class="detail-row"><span>Conditions selected</span><strong>'.concat(i.faults.length,'</strong></div><div class="detail-row"><span>Target</span><strong>').concat(d(e.company),'</strong></div><div class="detail-row"><span>Twin run</span><strong>').concat(d(t.entry),'</strong></div><label class="toggle-row"><input id="recovery" type="checkbox" ').concat(i.recovery?"checked":"",'><div>Preview recovery fixture<p>Switch to a separate scripted example of recovery behavior.</p></div></label><div class="callout amber">Passing means the expected recovery was observed in this scenario. It does not certify production safety.</div></div>'))).concat(k(),"</aside></div>")}let x=e=>c().runs.find(t=>t.id===e.runId)||l(),I=(e,t)=>x(e).faults.find(e=>e.id===t),P={perm:"Handle the 403 as a visible permission failure. Stop dependent writes and tell the operator which scope or connection needs renewal.",down:"Keep the completed write, persist the unfinished follow-up, and retry that follow-up when the service is available.",late:"Compare event versions or timestamps before applying a delayed event. Ignore an event older than the current state.",timeout:"Create one stable idempotency key for the logical operation, reuse it on every retry, and verify the final provider state.",dup:"Deduplicate by a stable request or event ID with an atomic guard before changing state.",rate:"Respect Retry-After, use bounded backoff, and persist enough context to resume without dropping the operation."};function O(e){var t,a;return e.faults.length?e.pass?Math.max(...e.faults.map(t=>{var a,s;return null!=(s=null==(a=I(e,t))?void 0:a.passCount)?s:1})):null!=(a=null==(t=I(e,e.faults[0]))?void 0:t.failCount)?a:0:1}function D(e){let t=c(),a=x(e),s="run_".concat(String(e.id).padStart(3,"0"));return["AgentTwin simulated run: ".concat(s," \xb7 ").concat(e.pass?"PASS":"FAIL"),"Example company: ".concat(t.company),"Workflow: ".concat(a.entry," \xb7 ").concat(a.label),"Faults: ".concat(e.faults.length?e.faults.map(t=>"".concat(I(e,t).name," (").concat(I(e,t).code,")")).join("; "):"none (baseline)"),"State: ".concat(a.stateKey," 0 → ").concat(O(e)),"Failed assertions: ".concat(e.pass?0:e.faults.length),"Production writes: 0","Illustrative source: ".concat(a.testFile)].join("\n")}function N(e){let t=x(e),a=e.faults.map(t=>{let a=I(e,t);return["- ".concat(a.name,": ").concat(a.failure.t,". ").concat(a.failure.d)," Suggested change: ".concat(P[t])," Passing behavior: ".concat(a.recovery.t,". ").concat(a.recovery.d)].join("\n")});return["Help me fix a failing integration workflow in my own repository.","This AgentTwin result is a synthetic demonstration. Inspect the real code and verify every assumption before changing it.","","Workflow: ".concat(t.entry," (").concat(t.label,")"),"Illustrative test path: ".concat(t.testFile," (this may not exist in my repository)"),"Run: run_".concat(String(e.id).padStart(3,"0")),"","Observed failure and suggested direction:",...a,"","Expected final state: one correct ".concat(t.stateKey," change, no duplicate or lost side effects, and zero failed assertions."),"Observed final state: ".concat(t.stateKey," changed from 0 to ").concat(O(e),"; ").concat(e.faults.length," assertion(s) failed."),"","Please locate the matching workflow, identify the actual root cause, make the smallest safe code change, add a regression test for this fault, and report what changed. Then rerun the same scenario and compare the final state and assertions. Do not treat the demo recovery fixture as a patch."].join("\n")}function L(){let e=i.runs.at(-1);if(!e)return g("No result yet",'<div class="empty"><h2>Run a workflow first.</h2><p>AgentTwin will show the outcome, the cause, and your next action here.</p><div class="row-buttons" style="justify-content:center">'.concat(h("Choose a workflow","run-page"),"</div></div>"));let t=x(e),a=!e.pass,s=e.pass?e.faults.length?"handled_error":"completed":"inconsistent",n=e.faults.length?e.faults.map(t=>I(e,t).recovery.t).join("; "):t.settled,o=a?e.faults.map(t=>I(e,t).failure.t).join("; "):"Expected state and assertions matched in this simulated run.",r='<section class="panel"><div class="result-banner '.concat(a?"failed":"",'"><div class="result-icon">').concat(a?"!":"✓","</div><div><h2>").concat(a?"Failed: the final state is wrong":"Passed in the simulated replica","</h2><p>run_").concat(String(e.id).padStart(3,"0")," \xb7 ").concat(e.recovery?"Recovery fixture":"Original fixture"," \xb7 ").concat(e.faults.length?"".concat(e.faults.length," fault").concat(1===e.faults.length?"":"s"):"Baseline",'</p></div></div><div class="decision-summary"><div><span>Expected</span><strong>').concat(d(n),"</strong></div><div><span>Observed</span><strong>").concat(d(o),'</strong></div></div><div class="tabs" role="tablist">').concat(["timeline","state diff","assertions"].map(e=>'<button class="tab '.concat(i.tab===e?"active":"",'" role="tab" aria-selected="').concat(i.tab===e,'" data-tab="').concat(e,'">').concat(e[0].toUpperCase()+e.slice(1),"</button>")).join(""),"</div>").concat("timeline"===i.tab?'<div class="timeline">'.concat(e.events.map(e=>'<div class="event '.concat(e.error?"error":"",'"><time>').concat(e.time,'</time><i class="line-dot"></i><div><strong>').concat(e.title,"</strong><p>").concat(e.desc,"</p></div>").concat(u(e.status,"INJECTED"===e.status?"amber":e.error?"red":""),"</div>")).join(""),"</div>"):"state diff"===i.tab?'<div class="panel-body"><div class="code"><span class="comment"># snapshot_001 → run_'.concat(String(e.id).padStart(3,"0"),"</span>\nworkflow.status: idle → ").concat(s,"\n").concat(t.stateKey,": 0 → ").concat(O(e),"\nproduction.writes: 0 → 0\nassertions.failed: 0 → ").concat(a?e.faults.length:0,'</div><p class="aside-note">Illustrative changes from the scripted demo, not a production trace.</p></div>'):'<div class="panel-body">'.concat(e.faults.length?e.faults.map(t=>{let a=I(e,t);return'<div class="detail-row"><span>'.concat(d(e.pass?a.recovery.t:a.failure.t),"</span>").concat(u(e.pass?"PASS":"FAIL",e.pass?"":"red"),"</div>")}).join(""):'<div class="detail-row"><span>Expected state created exactly once</span>'.concat(u("PASS"),"</div>"),'<div class="detail-row"><span>No production writes</span>').concat(u("PASS"),'</div><div class="detail-row"><span>No external messages delivered</span>').concat(u("PASS"),"</div></div>"),"</section>"),c=a?g("What broke and how to fix it",'<div class="panel-body"><p class="aside-note">These causes come from the demo fixture. Confirm them against your actual code and logs.</p>'.concat(e.faults.map(t=>{let a=I(e,t);return'<div class="diagnosis-item"><span class="eyebrow">'.concat(d(a.name)," \xb7 ").concat(d(a.code),"</span><h3>").concat(d(a.failure.t),"</h3><p>").concat(d(a.failure.d),"</p><p><strong>Change to try:</strong> ").concat(d(P[t]),"</p></div>")}).join(""),"</div>")):"",l=a?g("Next: fix your code, then rerun",'<div class="panel-body"><div class="action-steps"><div><b>1</b><span>Copy this fix prompt into your coding agent or use it to edit the workflow yourself.</span></div><div><b>2</b><span>Make the code change and add a regression test in your repository.</span></div><div><b>3</b><span>Rerun the same fault and check that the final state and assertions pass.</span></div></div><div class="code fix-prompt">'.concat(d(N(e)),'</div><div class="row-buttons">').concat(h("Copy fix prompt","copy-fix","primary")).concat(h("Preview recovery fixture","preview-recovery",""),'</div><p class="safe-note">This prototype cannot read or patch your repository. The recovery preview is a separate scripted fixture.</p></div>')):g("What to do next",'<div class="panel-body"><p class="aside-note">The expected state matched in this simulated run. Keep the scenario as a regression target, then test your real code when a connected runner exists.</p><div class="code fix-prompt">'.concat(d(D(e)),'</div><div class="row-buttons">').concat(h("Copy result report","copy-evidence","primary")).concat(h("Try another failure","fault-page",""),"</div></div>")),p=g("Repeat the same conditions",'<div class="panel-body"><div class="detail-row"><span>Starting state</span><strong>snapshot_001</strong></div><div class="detail-row"><span>Injected faults</span><strong>'.concat(e.faults.length,'</strong></div><div class="detail-row"><span>Result</span>').concat(u(e.pass?"PASS":"FAIL",e.pass?"":"red"),'</div><p class="aside-note" style="margin-top:15px">Rerun uses the same scripted implementation and faults. Reset clears the faults and returns to workflow setup.</p>').concat(h("Rerun current fixture","rerun","primary full",i.busy)).concat(h("Reset to baseline","reset","full"),'<p class="safe-note">All results are simulated.</p></div>'));return'<div class="grid"><div class="stacked">'.concat(r).concat(c).concat(l,'</div><aside class="stacked">').concat(p).concat(k(),"</aside></div>")}let F=["Connect production.","Your production. A safe replica.","Real workflows. Safe consequences.","Find the failures before they find you.","See what broke. Know what to do."],M=["Choose an example customer, then map its production stack before creating an isolated test environment.","Review what is copied, what is simulated, and what stays untouched.","Pick one of the workflows this team already has in flight, then run it against a repeatable baseline.","Put the same workflow through conditions a happy-path test misses.","Read the failed assertion, copy a fix prompt, change your code, and rerun the same scenario. This prototype only previews the recovery behavior."];function K(){let e=c();t("#app").innerHTML='<div class="announce"><span class="dot"></span> Interactive prototype \xb7 all data synthetic \xb7 no live systems connected</div><header class="topnav"><div class="brand"><img class="brandmark" src="assets/logo/mark-twin-rings.svg?v=white-rings" alt="" width="28" height="28">AgentTwin<small>α</small></div><nav class="navlinks" aria-label="Prototype navigation"><span class="navlink active">Customers</span><span class="navlink">Workflows</span><span class="navlink">Receipts</span><span class="navlink">Docs</span></nav><div class="nav-right"><span class="demo-pill">DEMO MODE</span><span class="avatar">SS</span></div></header><section class="hero"><div class="hero-inner"><div class="eyebrow">ENVIRONMENT / '.concat(i.replica?"REPLICA":"SETUP",'</div><h1 tabindex="-1" id="step-title">').concat(F[i.step],'</h1><p class="lead">').concat(M[i.step],'</p></div><div class="hero-side">').concat(i.connected?u(i.replica?"Replica isolated":"Discovery complete"):u("No live connections","gray"),'</div></section><div class="appwindow"><nav class="sidebar" aria-label="Main navigation"><div class="workspace"><span class="avatar">AT</span><div>Customer workspace<div class="secondary">Pick a company to model</div></div></div><div class="nav-label">Build confidence</div>').concat(a.map((e,t)=>'<button class="navbtn '.concat(i.step===t?"active":"",'" data-step="').concat(t,'" ').concat(!f(t)||i.busy?"disabled":"",'><span class="navnum">0').concat(t+1,"</span>").concat(e,"</button>")).join(""),'<div class="sidebar-bottom"><span class="demo-pill"><i class="dot"></i> INTERACTIVE PROTOTYPE</span><p style="margin-top:12px">A safe place to break things.</p><p class="subtle" style="font-size:11px;margin-top:8px">Illustrative data \xb7 no live connections</p></div></nav><main class="main"><header class="topbar"><span class="mobile-brand">AgentTwin</span><div class="crumb"><span class="subtle">Workspace</span><span class="subtle">/</span><span>').concat(d(e.company),'</span><span class="subtle">/</span><span>').concat(a[i.step],'</span></div><div class="topright"><span class="demo-pill">DEMO MODE</span><span class="avatar">SS</span></div></header><div class="main-inner"><div class="steps" aria-label="Setup progress">').concat(a.map((e,t)=>'<button class="step '.concat(i.step===t?"current":i.step>t?"done":"",'" data-step="').concat(t,'" ').concat(!f(t)||i.busy?"disabled":"","><b>").concat(i.step>t?"✓":t+1,"</b>").concat(s[t],"</button>")).join(""),"</div>").concat(i.notice?'<div class="notice" role="status"><strong>'.concat(d(i.notice),"</strong></div>"):"").concat([C,R,E,A,L][i.step](),'<footer class="bottom-note"><span>AGENTTWIN / PRODUCTION REPLICA WORKSPACE</span><span>No real systems are touched.</span></footer></div></main></div></div>')}async function H(e){return new Promise(t=>setTimeout(t,e))}async function j(e){if(!i.busy)if(i.notice="","discover"===e){if(i.connected)return w(1);i.busy=!0,K(),await H(1e3),i.connected=!0,i.busy=!1,i.step=1,K(),y("Discovered ".concat(c().services.length," dependencies. Review your replica."))}else if("create"===e){var a,s;let e=null==(a=t("#replica-name"))?void 0:a.value.trim();if(!e||!/^[a-z0-9][a-z0-9-]{0,39}$/.test(e)){b("Use 1–40 lowercase letters, numbers, or hyphens."),null==(s=t("#replica-name"))||s.focus();return}i.name=e,i.busy=!0,K(),await H(1200),i.replica=!0,i.busy=!1,i.step=2,K(),y("Test replica created. Ready to run a simulated workflow.")}else if("run-page"===e)w(2);else if("fault-page"===e)w(3);else if(["run","rerun","preview-recovery"].includes(e)){if(!i.replica)return;if("rerun"===e||"preview-recovery"===e){let t=i.runs.at(-1);if(!t)return;i.faults=[...t.faults],i.recovery="preview-recovery"===e||t.recovery}i.busy=!0,K(),await H(1100),i.runs.push(function(){let e=l(),t=[...i.faults],a=i.recovery,s=!t.length||a,n=[{time:"0.00s",title:"Baseline restored",desc:"snapshot_001 \xb7 synthetic records and test identities",status:"READY"},{time:"0.08s",title:e.startTitle,desc:e.startEvent,status:"START"}];return t.forEach((t,s)=>{let o=e.faults.find(e=>e.id===t);n.push({time:(.2+.3*s).toFixed(2)+"s",title:o.name,desc:o.desc,status:"INJECTED",error:!0}),n.push({time:(.35+.3*s).toFixed(2)+"s",title:a?o.recovery.t:o.failure.t,desc:a?o.recovery.d:o.failure.d,status:a?"HANDLED":"FAILED",error:!a})}),t.length||n.push({time:"0.46s",title:"State updated once",desc:e.settled,status:"PASS"}),n.push({time:(.7+.3*t.length).toFixed(2)+"s",title:"Final state assertions evaluated",desc:s?"No duplicate actions. Outcome recorded. No production writes.":"Unexpected state detected. Review the failed assertions.",status:s?"PASS":"FAIL",error:!s}),{id:i.runs.length+1,runId:e.id,runLabel:e.label,pass:s,faults:t,recovery:a,events:n}}()),i.busy=!1,i.step=4,i.tab="timeline",K(),y(i.runs.at(-1).pass?"Run passed. Expected outcome verified.":"Run failed. Read what broke, copy the fix prompt, and rerun.")}else if("clear"===e)i.faults=[],K();else if("copy-evidence"===e||"copy-fix"===e){let t=i.runs.at(-1);if(!t)return;let a="copy-fix"===e?N(t):D(t);try{await navigator.clipboard.writeText(a)}catch(t){let e=document.createElement("textarea");e.value=a,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select();try{document.execCommand("copy")}catch(e){}e.remove()}b("copy-fix"===e?"Fix prompt copied. Use it with your code, then rerun.":"Result report copied."),y("copy-fix"===e?"Fix prompt copied to the clipboard.":"Result report copied to the clipboard.")}else"reset"===e&&(i.faults=[],i.recovery=!1,i.step=2,i.notice="Replica restored to snapshot_001. Failure conditions cleared. Run history retained.",K(),y(i.notice))}if(document.addEventListener("click",e=>{let t=e.target.closest("button");t&&!t.disabled&&(t.dataset.action&&j(t.dataset.action),void 0!==t.dataset.step&&w(Number(t.dataset.step)),t.dataset.tab&&(i.tab=t.dataset.tab,K()))}),document.addEventListener("change",e=>{if(!i.busy){if("customer"===e.target.name&&(i.customer=e.target.value,i.name=c().name,i.runId=c().runs[0].id,i.connected=!1,i.replica=!1,i.runs=[],i.faults=[],i.recovery=!1,i.step=0,i.notice="",K(),y("Customer switched to ".concat(c().company,". ").concat(c().runs.length," twin runs available."))),"twinrun"===e.target.name){if(e.target.value===i.runId)return;i.runId=e.target.value,i.faults=[],i.recovery=!1,K(),y("Twin run selected: ".concat(l().label,"."))}"fault"===e.target.name&&(i.faults=e.target.checked?[...i.faults,e.target.value]:i.faults.filter(t=>t!==e.target.value),K()),"recovery"===e.target.id&&(i.recovery=e.target.checked,K())}}),K(),null==(e=document.modelContext)?void 0:e.registerTool)for(let e of[{name:"read_replica_demo",description:"Read current simulated replica and latest result. No production systems are connected.",inputSchema:{type:"object",properties:{},additionalProperties:!1},annotations:{readOnlyHint:!0},execute:()=>({connected:i.connected,replica:i.replica,customer:c().company,step:a[i.step],faults:[...i.faults],lastRun:i.runs.at(-1)||null})},{name:"configure_demo_failures",description:"Select failure conditions in the simulated replica. Does not run a test.",inputSchema:{type:"object",properties:{faults:{type:"array",items:{type:"string",enum:[...new Set(r.flatMap(e=>e.runs.flatMap(e=>e.faults.map(e=>e.id))))]}}},required:["faults"],additionalProperties:!1},annotations:{readOnlyHint:!1},execute:e=>{if(!i.replica||i.busy)throw Error("Create an idle replica first");if(!e||!Array.isArray(e.faults)||e.faults.some(e=>!l().faults.some(t=>t.id===e)))throw Error("Invalid failure selection");return i.faults=[...new Set(e.faults)],i.step=3,K(),{faults:i.faults}}}])try{Promise.resolve(document.modelContext.registerTool(e)).catch(()=>{})}catch(e){}}()}),()=>{e=!0}},[]),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("a",{href:"/dashboard/",className:"dashboard-link",children:"View actual test results in the AgentTwin dashboard ↗"}),(0,s.jsx)("div",{id:"app"}),(0,s.jsx)("div",{id:"announcer",className:"sr-only",role:"status","aria-live":"polite"})]})}},3834:(e,t,a)=>{Promise.resolve().then(a.bind(a,3413)),Promise.resolve().then(a.t.bind(a,3241,23))}},e=>{e.O(0,[6654,8441,1255,7358],()=>e(e.s=3834)),_N_E=e.O()}]);
|
package/dist/dashboard/assets/next/static/chunks/app/docs/[[...slug]]/page-db473994608d5c77.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7870],{1636:(e,t,n)=>{"use strict";n.d(t,{DocsCodeBlock:()=>i});var a=n(5155),r=n(3051);function i(e){var t,n,i;let{children:o,...s}=e,d=Array.isArray(o)?o[0]:o,c=null!=(i=null==d||null==(t=d.props)?void 0:t.className)?i:"",l=null==(n=/language-([\w-]+)/.exec(c))?void 0:n[1],u="sh"===l||"bash"===l||"shell"===l||"console"===l?"Terminal":l?l.toUpperCase():"Code";return(0,a.jsx)(r.NG,{title:u,children:(0,a.jsx)("pre",{...s,children:o})})}n(3906)},2285:(e,t,n)=>{"use strict";n.d(t,{I:()=>i});var a=n(5155);let r={house:"m3 10.5 9-7.5 9 7.5M5.5 9v10.5h13V9M9.5 19.5v-6h5v6",activity:"M3 12h4l3-8 4 16 3-8h4",boxes:"m12 3 4 2v4l-4 2-4-2V5l4-2Zm-6 9 4 2v4l-4 2-4-2v-4l4-2Zm12 0 4 2v4l-4 2-4-2v-4l4-2Z",workflow:"M6 3v12a3 3 0 0 0 3 3h9M6 3 3 6m3-3 3 3m6 9 3 3 3-3","timer-off":"M12 21a8 8 0 1 0 0-16 8 8 0 0 0 0 16Zm0-12v4l-3 2M9 2h6","badge-check":"M12 3l2.2 1.6 2.7-.2.9 2.6 2.2 1.6-1 2.5 1 2.5-2.2 1.6-.9 2.6-2.7-.2L12 21l-2.2-1.6-2.7.2-.9-2.6L4 15.4l1-2.5-1-2.5 2.2-1.6.9-2.6 2.7.2L12 3Zm-2 9 1.6 1.6L15 10",shield:"M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3Zm-3 9 2 2 4-4",layout:"M4 4h16v16H4V4Zm0 6h16M10 10v10",map:"m3 6 6-3 6 3 6-3v15l-6 3-6-3-6 3V6Zm6-3v15M15 6v15","mouse-pointer-click":"M9 9v10l2.5-2.5L14 21l1.8-.9-2.4-4.4H17L9 9Z",help:"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm-2-11a2 2 0 1 1 2.9 1.8c-.6.3-.9.8-.9 1.4v.3M12 17h.01","book-open":"M12 5v15M12 5C9 3 5 3 2 4v15c3-1 7-1 10 1M12 5c3-2 7-2 10-1v15c-3-1-7-1-10 1",layers:"m3 8 9-5 9 5-9 5-9-5Zm0 5 9 5 9-5M3 18l9 5 9-5",compass:"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm3.5-12.5-2 5-5 2 2-5 5-2Z","life-buoy":"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm0-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm0-3-6.5-6.5M12 12l6.5 6.5M12 12 5.5 18.5M12 12l6.5-6.5",globe:"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm-9-9h18M12 3c2.5 2.6 3.8 5.6 3.8 9S14.5 18.4 12 21c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3Z",calendar:"M4 6h16v14H4V6Zm0 5h16M8 3v4M16 3v4",play:"M8 5v14l11-7L8 5Z",sun:"M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10Zm0-14v2M12 19v2M3 12h2M19 12h2M5.6 5.6 7 7M17 17l1.4 1.4M18.4 5.6 17 7M7 17l-1.4 1.4",moon:"M20 13.5A8 8 0 0 1 10.5 4a8 8 0 1 0 9.5 9.5Z",search:"M11 18a7 7 0 1 0 0-14 7 7 0 0 0 0 14Zm5-2 4 4",copy:"M9 9h10v10H9V9ZM5 15V5h10",menu:"M4 7h16M4 12h16M4 17h16",close:"M6 6l12 12M18 6 6 18",chevron:"m9 5 7 7-7 7",sparkles:"m12 3 1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9L12 3Zm7 11.5.9 2.1 2.1.9-2.1.9-.9 2.1-.9-2.1-2.1-.9 2.1-.9.9-2.1Z",history:"M12 21a9 9 0 1 0-9-9m9 0v4m-9 5 1-4 4 1M3 3v5h5","flask-conical":"M9 3h6M10 3v6L4.5 17.5A2 2 0 0 0 6.2 21h11.6a2 2 0 0 0 1.7-3.5L14 9V3M7 15h10",network:"M5 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm14 0a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM5 21a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm14 0a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM5 5.5h14M12 5.5V18m-7 0h14m-7 0v-4"};function i(e){let{name:t,className:n}=e;return(0,a.jsx)("svg",{viewBox:"0 0 24 24",width:16,height:16,fill:"none",stroke:"currentColor",strokeWidth:1.7,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",className:n,children:(0,a.jsx)("path",{d:r[t]||r["book-open"]})})}},2782:(e,t,n)=>{Promise.resolve().then(n.bind(n,3190)),Promise.resolve().then(n.bind(n,8778)),Promise.resolve().then(n.bind(n,600)),Promise.resolve().then(n.bind(n,1036)),Promise.resolve().then(n.bind(n,7041)),Promise.resolve().then(n.bind(n,9557)),Promise.resolve().then(n.bind(n,441)),Promise.resolve().then(n.bind(n,5765)),Promise.resolve().then(n.bind(n,3878)),Promise.resolve().then(n.bind(n,7652)),Promise.resolve().then(n.bind(n,7714)),Promise.resolve().then(n.bind(n,1044)),Promise.resolve().then(n.bind(n,5064)),Promise.resolve().then(n.bind(n,7838)),Promise.resolve().then(n.bind(n,6471)),Promise.resolve().then(n.bind(n,1636)),Promise.resolve().then(n.bind(n,9050)),Promise.resolve().then(n.bind(n,7684)),Promise.resolve().then(n.t.bind(n,8566,23)),Promise.resolve().then(n.t.bind(n,8417,23))},3906:()=>{"undefined"==typeof navigator||"undefined"==typeof document||navigator.clipboard||Object.defineProperty(navigator,"clipboard",{value:{writeText:e=>new Promise((t,n)=>{let a=document.createElement("textarea");a.value=e,a.setAttribute("readonly",""),a.style.cssText="position:fixed;top:-9999px;left:-9999px;opacity:0",document.body.appendChild(a),a.select();try{if(!document.execCommand("copy"))throw Error("copy_rejected");t()}catch(e){n(e)}finally{a.remove()}})},configurable:!0})},7684:(e,t,n)=>{"use strict";n.d(t,{DocsCopyPage:()=>s});var a=n(5155),r=n(2115),i=n(2285);async function o(e){try{var t;if(null==(t=navigator.clipboard)?void 0:t.writeText)return void await navigator.clipboard.writeText(e)}catch(e){}let n=document.createElement("textarea");n.value=e,n.setAttribute("readonly",""),n.style.cssText="position:fixed;top:-9999px;left:-9999px;opacity:0",document.body.appendChild(n);let a=document.getSelection(),r=(null==a?void 0:a.rangeCount)?a.getRangeAt(0):null;n.select();try{if(!document.execCommand("copy"))throw Error("copy_rejected")}finally{n.remove(),r&&a&&(a.removeAllRanges(),a.addRange(r))}}function s(e){let{slug:t,title:n}=e,[s,d]=(0,r.useState)("idle"),c=(0,r.useRef)(void 0);return(0,r.useEffect)(()=>()=>clearTimeout(c.current),[]),(0,a.jsxs)("button",{type:"button",className:"docs-copy-page",onClick:()=>{(async()=>{try{let e=await fetch("index"===t?"/docs/index.md":"/docs/".concat(t,".md"));if(!e.ok)throw Error("unavailable");await o(await e.text()),d("done")}catch(e){d("failed")}clearTimeout(c.current),c.current=setTimeout(()=>d("idle"),2500)})()},title:"Copy ".concat(n," as Markdown"),children:["done"===s?"Copied":"failed"===s?"Copy unavailable":"Copy page",(0,a.jsx)(i.I,{name:"copy"})]})}},8417:()=>{},8566:()=>{},9050:(e,t,n)=>{"use strict";n.d(t,{DocsSearchTrigger:()=>R});var a,r=n(5155),i=n(2115),o=n(2285);let s=[{slug:"index",title:"Welcome to AgentTwin",group:"Start here",headingText:"",headingId:"",text:"The handbook from repository discovery to a reproduced failure and a verified application fix."},{slug:"index",title:"Welcome to AgentTwin",group:"Start here",headingText:"Start with your project",headingId:"start-with-your-project",text:"Run this inside your repository with Node.js 22.12 or newer: npx agenttwin init Review the generated discovery. Init can offer an installed OpenCode session; other coding agents can use .agenttwin/AGENT-TASK.md . Analysis identifies candidates, required dependencies and missing inputs. It does not prove a workflow works. Connect your individual AgentTwin account in the dashboard . Run npx agenttwin login , complete the browser connection, then run npx agenttwin sync . Automation can supply AGENTTWIN TOKEN to send reviewed discovery metadata. You can also import .agenttwin/inventory.json manually. Discover, prepare, execute and inspect your actual code. Environment, Workflows, Runs, Settings and the account menu. Supported contracts and remaining gaps. Understand starting state, credentials and sandbox boundaries."},{slug:"index",title:"Welcome to AgentTwin",group:"Start here",headingText:"Coverage is explicit",headingId:"coverage-is-explicit",text:"The runtime supports custom HTTP collections, a bounded Slack API subset, PostgreSQL and Redis. Catalog selection declares a dependency; it does not implement a vendor adapter or create a real provider account. Unsupported behavior must be reviewed before execution. The product covers many workflows, including support, notifications, sales, payments and agent side effects. Refunds are an example, not the product boundary."},{slug:"index",title:"Welcome to AgentTwin",group:"Start here",headingText:"Read the handbook from start to finish",headingId:"read-the-handbook-from-start-to-finish",text:"Chapter What you will learn --- --- First verified fix Execute an example failure and prove a source-only repair Discover and test Move from repository signals to reviewed execution Prepare application code Build an entrypoint, configure twins and review the bundle Reusable worlds Provision, run, reset, extend and clean up Scenarios and fixtures Link synthetic identities and preserve immutable baselines Fidelity Understand operation coverage and provider limitations Safety Choose local or cloud boundaries and review credentials Evidence and retesting Diagnose failures and compare unchanged checks CLI and MCP Find commands, artifacts and coding-agent tools Troubleshooting Resolve setup, account and execution failures For a first-time user, start with the local quickstart before connecting a real project. For an existing workflow, begin with preparation. For a failed run, begin with evidence. The handbook describes current implemented contracts; planned features remain labeled in the roadmap."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"",headingId:"",text:"Run a real failure, inspect its evidence and verify a source-only repair."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"What you will accomplish",headingId:"what-you-will-accomplish",text:"The primary entry point is now: npx agenttwin init Bare npx agenttwin opens the same control menu. From it, review service coverage, select a reviewed world file, run its checks, explore seeded faults, replay the captured failure, verify a source-only patch, and save a trial as a regression. Account connection, reviewed sharing, incident imports and protected CI installation are also menu actions. npx agenttwin refresh updates discovery without executing your application. These changes describe the current checkout and require a matching published package for registry npx use. A world still needs explicit application files, synthetic starting state and correctness checks. AgentTwin does not automatically infer every business requirement or implement every detected provider. The menu's demo is labeled as an example. Noninteractive init performs discovery only. Seeded exploration currently varies timeout-after-write targets and delays, with an unfaulted control and fresh state for every trial. It does not reproduce OS scheduling. Captured trials preserve checks and application snapshots; replay uses the snapshot, while patch verification runs the current source against the same captured checks. Untriggered faults and unsupported operations remain incomplete. Commit a saved regression to a trusted baseline before requiring it in CI. The commands below are the advanced automation equivalents for a concrete walkthrough. Create a local test world, reproduce a lost-response retry that creates duplicate tickets, fix the application, and rerun the same checks. You need Node.js 22.12 or newer and a terminal. A dashboard account, Docker and cloud credentials are not required for this local example. This guide describes the current checkout. If an installed CLI does not expose world , scenario or contracts , check its version and use the built CLI from this repository. Do not assume an older published package has every capability shown here."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"1. Generate the example",headingId:"1-generate-the-example",text:"Run from a working directory where AgentTwin can save its local records: npx agenttwin example --out ./agenttwin-example npx agenttwin contracts --file ./agenttwin-example/reusable.world.json --json The example includes application source, a reusable world specification and support.scenario.json . Read the files before execution. The operation matrix establishes which requests the adapters actually support. The primary agenttwin.world.json is clean by default. Compare the same source and assertions with and without the fault: npx agenttwin run --file ./agenttwin-example/agenttwin.world.json --seed 00000000000000000000000000000001 --json npx agenttwin run --file ./agenttwin-example/agenttwin.world.json --fault timeout-after-write --seed 00000000000000000000000000000001 --json Expect exit 0 with one ticket and one notification, then exit 1 with two tickets and a triggered timeout-after-write fault. --fault none explicitly disables an active fault; --fault selects a declared faults preset or the active fault type, and --fault configured selects the active fault. Unconfigured selections are rejected. Verification needs the same selection (for example verify --file RECEIPT --world ./agenttwin-example/agenttwin.world.json --fault timeout-after-write ); replay automatically uses the effective world saved beside its receipt. No assertions change between the two runs. The separate reusable.world.json used below retains the active fault for the lifecycle and application-repair walkthrough."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"2. Save the baseline and create a world",headingId:"2-save-the-baseline-and-create-a-world",text:"npx agenttwin scenario save --file ./agenttwin-example/support.scenario.json --json npx agenttwin world create --file ./agenttwin-example/reusable.world.json --scenario support retry@1 --ttl 3600 --json Keep the returned world ID. Endpoints and generated credentials belong to this test world. Keep credentials private. The services run on loopback; the application runs on your computer, with host filesystem and network access."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"3. Reproduce and inspect",headingId:"3-reproduce-and-inspect",text:"npx agenttwin world run --id WORLD ID --json npx agenttwin receipt --id RUN ID --json Replace the uppercase placeholders with returned IDs. The first run is expected to fail: the ticket write commits, its response is delayed, and a retry without a stable idempotency key creates another ticket. Find the expected one-ticket outcome, actual two-ticket count and ordered service events. An intentional failed test is useful evidence, not a setup error."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"4. Patch application source only",headingId:"4-patch-application-source-only",text:"Open agenttwin-example/workflow.mjs . The generated example contains a safe flag: set its assignment to const safe = true to activate the stable-key request and retry. Review that code to understand the repair. In your own application, implement the same behavior in the actual retry path rather than adding an example flag. Leave the world specification, assertions and scenario version unchanged. Reusing the same baseline makes the before/after comparison meaningful. npx agenttwin world run --id WORLD ID --json npx agenttwin receipt --id NEW RUN ID --json npx agenttwin verify --file .agenttwin/runs/NEW RUN ID/run.json --world ./agenttwin-example/reusable.world.json --scenario support retry@1 --json Expect one ticket, one notification and unchanged customer records. Check that the source digest changed while specification and scenario digests stayed fixed. Verification recomputes evidence and checks freshness; it is not independent execution attestation."},{slug:"quickstart",title:"Your first verified fix",group:"Start here",headingText:"5. Inspect in the dashboard and clean up",headingId:"5-inspect-in-the-dashboard-and-clean-up",text:"Open Runs and import the broken and fixed run.json receipts, or connect your account and use npx agenttwin sync . Manual imports stay in the browser session. Compare final state, checks and recorded steps, not just the green status. npx agenttwin world teardown --id WORLD ID --json Teardown closes the world endpoints. Keep receipts as evidence. Next, prepare your own workflow or read about scenario versions ."},{slug:"status",title:"What works today",group:"Start here",headingText:"",headingId:"",text:"Shipped capabilities, engineering verification and remaining limitations."},{slug:"status",title:"What works today",group:"Start here",headingText:"Remaining gaps",headingId:"remaining-gaps",text:"Arbitrary vendor API compatibility, real third-party account provisioning, native macOS execution, universal workflow extraction and unattended repairs are not implemented. Reviewed local Chromium recipes, bounded background completion, immutable incident regressions and a protected PR check template are available. Protected browser/background and PostgreSQL/Redis CI execution remain unsupported. Coding-agent analysis still needs reviewed invocation, fixtures and outcome expectations. The API uses a single-instance durable disk store. Distributed scheduling, billing, deletion reconciliation and complete production monitoring remain work to do."},{slug:"status",title:"What works today",group:"Start here",headingText:"Verification and data",headingId:"verification-and-data",text:"Engineering checks passed hosted execution, configured PostgreSQL/Redis assertions, account isolation/revocation, cancellation and persistence. The verified October 14 checkout passed 151 CLI tests and 17 web evidence tests. The guided npx agenttwin init control menu adds seeded timeout-after-write exploration, captured-source replay, unchanged-check patch verification and saved trial regressions. Seeds control fault selection and delays, not OS scheduling; public npx use requires the updated package to be published. Official Stripe SDK calls, runtime observation, Chromium recipes, background completion, incident imports and CI installation are covered. A real Docker check reproduced duplicate writes, passed the patched commit with unchanged checks, and ignored candidate changes to the grading specification. The packaged MCP loop reproduced duplicate writes, patched only source, reran unchanged checks, verified the receipt and exercised reset, extension and teardown. The October 18 source increment (0.3.8, not yet npm latest when checked October 19) adds thirteen vendored HTTP twins (GitHub, Linear, Notion, HubSpot, Shopify, Datadog, Gmail, Google Calendar, GitLab, Jira, Discord, Twilio, Zendesk), client-side seeded runs with exact replay , seed-matrix verdicts, the bounded shrink bisection, blackhole/server-error/duplicate-write fault classes, named property checks, and the public docs v1/ai/search endpoint; 348 CLI tests and a clean typecheck cover the release. Dashboard checks verified saved preferences, account connect/disconnect and full-width sidebar collapse on desktop and mobile. These checks are not customer adoption evidence or proof of production equivalence. The production dashboard starts with an empty inventory and receipt list. The separate prototype uses fictional scenarios; its outcomes are scripted."},{slug:"status",title:"What works today",group:"Start here",headingText:"Latest integration verification",headingId:"latest-integration-verification",text:"Main commit 79cbcd3 combines returning-user onboarding and project removal with organization SSO/Keycloak work. Its CLI and docs GitHub checks passed. Combined local verification passed 358 CLI tests (including a browser-suite rerun after installing Chromium), 17 web tests, production builds and browser onboarding/project-removal checks. Commit 3328277 adds shared-context automation with six passing focused tests and a successful GitHub metadata sync. These are recorded engineering results; this documentation update did not rerun those suites. Live OAuth/OTP acceptance, deployment provenance, clean npm onboarding and a complete real pilot remain separate gates."},{slug:"concepts",title:"Worlds, twins, and replicas",group:"Start here",headingText:"",headingId:"",text:"The vocabulary behind AgentTwin: worlds, service twins, replicas, baselines, and regression artifacts."},{slug:"concepts",title:"Worlds, twins, and replicas",group:"Start here",headingText:"Core vocabulary",headingId:"core-vocabulary",text:"Term Meaning --- --- World A set of service twins plus the shared entities and events that link them. Twin A service stand-in that implements the subset of provider behavior a workflow depends on. Replica A disposable, isolated test copy of a world, created from a baseline. Baseline The versioned starting state a run begins from and can be restored to. Fault injection A deterministic failure applied at a chosen point in a run. Manifest The declared coverage of a replica: what is verified, modeled, or unsupported. Regression artifact The saved starting state, fault point, input, and assertions from a reproduced incident."},{slug:"concepts",title:"Worlds, twins, and replicas",group:"Start here",headingText:'Why "world" and not "mock"',headingId:"why-world-and-not-mock",text:"One customer should be the same logical person in a billing system, a CRM, an inbox, and a support tool. A refund can update billing state, emit a webhook, change an internal record, and trigger a notification. A world evaluates that whole chain, not a single endpoint in isolation."},{slug:"concepts",title:"Worlds, twins, and replicas",group:"Start here",headingText:"What makes a world useful",headingId:"what-makes-a-world-useful",text:"- Shared state — related records across services represent the same people, accounts, and business events. - Observable effects — writes and asynchronous events are recorded so a developer can inspect what actually changed. - Repeatability — a baseline can be restored, a run repeated, and time or randomness controlled so failures can be compared. - Branching — one baseline can be explored under several independent scenarios without contaminating the others. - Failure controls — supported faults can occur at meaningful points, including after a service has already applied a write. - Outcome verification — correctness is checked against final world state and invariants, not only the agent's natural-language explanation. - Honest fidelity — each twin should state what is supported, what has been verified, what is unknown, and when verification last ran. Current runs use explicit fixtures, supported service contracts and fresh sandbox provisioning. Automatic shared-identity compilation, coordinated snapshots and control of all clocks or randomness are outside current coverage."},{slug:"concepts",title:"Worlds, twins, and replicas",group:"Start here",headingText:"The agent should not have to know",headingId:"the-agent-should-not-have-to-know",text:"The agent should not have to know whether it is talking to production or a test world beyond the configuration boundary. The developer, however, should always be able to tell which world is active and what that world can faithfully simulate. How a replica publishes its limits: verified, modeled, and unsupported behavior."},{slug:"workflow",title:"Discover, test and retest",group:"Use your application",headingText:"",headingId:"",text:"The usable path from repository discovery to evidence from a CLI or cloud run."},{slug:"preparation",title:"Prepare your actual application",group:"Use your application",headingText:"",headingId:"",text:"Turn a discovered candidate into an executable, reviewed test bundle."},{slug:"preparation",title:"Prepare your actual application",group:"Use your application",headingText:"Discovery is the starting point",headingId:"discovery-is-the-starting-point",text:"Run npx agenttwin init inside your application repository. Review .agenttwin/inventory.json and the workflow candidates. An entrypoint or dependency found in source is a candidate, not proof of provider access or a runnable test. Choose one narrow workflow with observable effects. Identify its built Node entrypoint, required inputs, every service operation, synthetic starting records and expected outputs. Other coding agents can use .agenttwin/AGENT-TASK.md ; discovery does not automatically supply a correct executable test."},{slug:"preparation",title:"Prepare your actual application",group:"Use your application",headingText:"Build and configure the entrypoint",headingId:"build-and-configure-the-entrypoint",text:"The runtime does not transpile TypeScript or install application dependencies. Bundle them first and list the required built files. command is an argv array beginning with node . Application file paths resolve relative to the world specification. Configure test clients with generated AGENTTWIN URL and AGENTTWIN TOKEN values. A production SDK requires a supported base-URL override and supported operations; merely replacing a token is insufficient. Use synthetic IDs and avoid copying production credentials into the bundle."},{slug:"preparation",title:"Prepare your actual application",group:"Use your application",headingText:"A preparation contract",headingId:"a-preparation-contract",text:'Save this as preparation.json beside your built workflow.mjs . Replace both discovery IDs with the actual IDs in your inventory. This example prepares a Slack notification; it is not a complete Slack replica. { "schema": "agenttwin/preparation-v1", "workflowId": "YOUR DISCOVERED WORKFLOW ID", "world": { "schema": "agenttwin/world-v1", "name": "notification", "files": "workflow.mjs" , "command": "node", "workflow.mjs" , "timeoutSeconds": 20, "services": { "name": "slack", "adapter": "slack", "collections": {"path": "/messages", "seed": }, {"path": "/channels", "seed": {"id": "C TEST", "name": "test"} } } , "assertions": {"service": "slack", "path": "/messages", "count": 1} }, "mappings": { "toolId": "YOUR DISCOVERED SLACK TOOL ID", "service": "slack", "contract": "slack", "operations": "chat.postMessage" , "reviewed": true } } Your application must send a message to the seeded channel using the generated connection information. The assertion checks one recorded message; add stronger observable checks appropriate to your workflow. Include every recorded candidate operation in reviewed mappings. Preparation rejects missing or unsupported mappings, but cannot establish that static discovery found every behavior in arbitrary source.'},{slug:"preparation",title:"Prepare your actual application",group:"Use your application",headingText:"Prepare, review, execute",headingId:"prepare-review-execute",text:"npx agenttwin prepare --file preparation.json --out .agenttwin/prepared/notification npx agenttwin contracts --file .agenttwin/prepared/notification/agenttwin.world.json --json npx agenttwin run --file .agenttwin/prepared/notification/agenttwin.world.json --json Preparation copies unchanged listed source and writes the world spec, a SHA-256 manifest and agenttwin.bundle.json . It does not execute the application. Review the upload list, bundled source, fixtures and checks before running or uploading. Local execution supports HTTP collections and bounded Slack operations. PostgreSQL and Redis need explicit cloud execution. In Workflows, select the bundle and review its upload before submitting a cloud job. See execution boundaries ."},{slug:"preparation",title:"Prepare your actual application",group:"Use your application",headingText:"Retest the right files",headingId:"retest-the-right-files",text:"For a one-shot prepared bundle, changing your original source does not update a previously copied bundle: rebuild and prepare again. For a reusable world, every run restages the files listed by that world's specification and resets its baseline. Confirm which files the spec references before patching. Do not make a failing check pass by weakening the outcome or removing the fault. Inspect evidence, patch source and compare receipts under unchanged test conditions. Understand the receipt before approving a repair."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"",headingId:"",text:"Use the environment map, workflows, run evidence and working settings."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Environment",headingId:"environment",text:"Start with Connect project and npx agenttwin init . Agent-analysis and sync instructions expand when needed. The environment map appears after discovery or explicit resource selection. It shows those resources with logos and coverage labels; no demonstration services are preselected. Drag empty canvas space to pan, drag cards to move them, or use zoom, Reset view and Arrange. Search the selected-resource list to find a tool, inspect its coverage and remove it. Removal can be undone. Manual catalog selection is a declaration, not account access or provisioning. Once connected, Environment shows the project name and resource map. View all workflows opens the complete searchable candidate inventory."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Workflows",headingId:"workflows",text:"Review discovered entrypoints and dependencies. Prepare workflow creates a preparation task for your coding agent using the selected candidate. Package real application files and reviewed operation mappings with the CLI, then upload the resulting bundle to execute. Saved configurations store fixtures, faults and assertions separately from application files. Candidates with recorded evidence link to their run results."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Runs",headingId:"runs",text:"Run history contains loaded account results and any run.json files you explicitly import. Filter by repository, workflow or outcome; search by test name, revision or run ID. On phones, use Select test to switch results. Active executions and executions without a loaded receipt appear separately above the history; completed tests are not duplicated there. - Summary identifies the workflow, test configuration, repository, tested revision, runner and command. It explains the result and lists each expected outcome beside its observed value. Failed checks appear first. Failure scenarios show whether an injected condition actually activated. - Recorded steps shows observed service activity in sequence, including writes and activated failures. It is not a complete trace of every application step. - Run history lists other tests of the same workflow and repository. Select a baseline to compare checks, revisions and final collection state. Different test configurations, starting state, source digests or fault settings are highlighted; a comparison does not establish the cause of a regression. - Technical details contains execution output, state changes, runner metadata and the original receipt. Use Copy fix prompt for a failed test or Copy review prompt for a passed test. The task includes the workflow, available source entrypoint, tested revision, checks, recorded activity and output. Give it to your coding agent in the original repository, review the fix, rerun the same test and sync the new receipt. Local CLI execution is the default; use a cloud machine only when needed. You can also preview or download the task, export a result, or export the selected comparison. A passed result covers its recorded checks, not every behavior of the workflow. A failed check explains what differed; the underlying cause may still require inspecting source and logs. Missing repository or Git information is shown as Not recorded , not inferred. Imported files remain in the current browser session and are not uploaded. The API currently lists the latest 100 account jobs; Settings controls how many receipts load per refresh, and later refreshes fetch unloaded receipts."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Account menu",headingId:"account-menu",text:"Click the initials in the top-right corner to open account actions: Account & settings, View runs and Disconnect account. Connection status reflects the current tab. Escape or a click outside closes the menu. Disconnect is available only when an account is connected."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Settings",headingId:"settings",text:"Setting Effect --- --- Workspace name Changes the dashboard label and initials in this browser Default execution limit Suggested duration in coding-agent preparation tasks; each reviewed bundle keeps its own execution limit Refresh automatically Polls account discovery and active jobs while the tab is visible; manual Refresh workspace remains available Compact lists Reduces workflow and receipt row spacing Reduce motion Disables transitions and smooth scrolling; system preferences are also respected Account connection API URL, token visibility, Connect account, Refresh workspace and Disconnect Use Save preferences to persist changes or Reset defaults to restore browser preferences. Preferences are not shared team settings. Account tokens stay in memory and are cleared on reload or disconnect; they are not saved with preferences."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Navigation and storage",headingId:"navigation-and-storage",text:"The top navigation contains Home, Environment, Workflows, Runs and Settings. The logo returns to Home. Home uses the full-width artwork layout. Other views have a collapsible project sidebar; closing it leaves a full-width content column. Narrow screens use the top navigation and a short repository row. Documentation uses a book icon; infrastructure implementation labels do not occupy the sidebar. Manual declarations, map layout and dashboard preferences persist in browser storage. Imported discovery and receipts stay in memory. Synced discovery and submitted run evidence persist on the account’s API store. Sync sends metadata; executing a reviewed bundle uploads the selected application files. No production OAuth session or production account is cloned. Open the dashboard . The compatibility dashboard is available at the API origin ."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Failure scenarios",headingId:"failure-scenarios",text:"In Workflows → Advanced: saved configurations and failure scenarios → Edit configuration , select healthy execution or Timeout after write , choose a service collection, and set the response delay. Apply the scenario to the draft, save or export it, and rebuild your application bundle before uploading. Previously reviewed bundles are not changed by this editor. Timeout after write commits a write before delaying its response. Your application decides whether to retry. Inspect fault activation and final-state assertions in Runs to detect duplicate effects. Other fault types are not currently implemented. Settings includes a results-per-refresh limit for larger workspaces. Account changes clear transient resource selections, receipts, prepared uploads and upload approval. Server quotas and organization access policies are not browser preferences."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Guided workflow",headingId:"guided-workflow",text:"Home shows the next action for your connected project, its detected resources, workflow candidates, recent results, active work and failing assertions. The workflow assistant opens from a compact dock at the bottom of Home. The artwork fades behind the workspace and carries “What should your agent test?”. Customize lets you choose which overview cards appear; those choices and your company/name preferences are saved in this browser. Workflows shows ten candidates per page and searches the complete inventory. Selecting a workflow opens a focused preparation guide with a task for your coding agent and the upload step. Saved JSON configurations and failure controls remain under Advanced: saved configurations and failure scenarios . Preparing application files still happens in your repository; dashboard chat cannot do it automatically."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Repositories and chat",headingId:"repositories-and-chat",text:"Sync each repository with the same AgentTwin account. The sidebar lists synced repositories and the selected repository’s workflow candidates; selecting a repository changes its environment, saved contracts and chat context. Repository names identify inventories, so use distinct names for separate products. Run history currently spans the account. The sidebar is hidden in Settings. Open the chat dock to see its connection status. Connect your account in Settings before sending a message. Chat explains discovery metadata, saved contracts and selected run evidence; use Workflows to prepare and execute code."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"CLI tests and Git activity",headingId:"cli-tests-and-git-activity",text:"Test reviewed bundled Node workflows through npx agenttwin run --file path/to/agenttwin.world.json from the original repository. This uses in-process HTTP twins by default. Review output and fixtures, then run npx agenttwin sync to send discovery, Git metadata and CLI results to the website. CLI execution uses your machine and is not a VM isolation boundary. Select --runtime hosted or --runtime e2b explicitly for a workflow that needs a cloud machine. PostgreSQL and Redis worlds currently require cloud execution. There is no automatic VM provisioning for discovery, chat or dashboard viewing. Home shows recorded test results, adapter activities and failed checks. Git activity shows up to 100 commits from 14 days, total repository commits, branch and HEAD. Changed workflow entrypoint paths are flagged since the previous sync. Runs retain the tested SHA and source digests; older passing tests do not prove a newer commit passes. This does not yet trace transitive changes across every workflow."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Workflow review",headingId:"workflow-review",text:"Workflows separates discovered code paths from recorded test evidence. Filter by activity, or choose Not tested , Needs attention , Retest changes , or Last test passed . Each card shows its dependencies and preparation needs; expand Source and setup to inspect its entrypoint and open resource setup. Test status only uses receipts with a matching workflow ID and recorded repository. Missing repository context cannot establish coverage. A changed entrypoint or newer Git revision marks a previously passing workflow for retesting. Counts reflect loaded results, not every historical test. Choose Prepare a test to preview, copy or download a task for your coding agent. The task includes the latest recorded result when available. Review the generated files and assertions, run locally, then sync. Expand cloud execution only when the workflow requires a cloud machine."},{slug:"dashboard",title:"Dashboard guide",group:"Use your application",headingText:"Time-of-day artwork",headingId:"time-of-day-artwork",text:"Home artwork spans the full width, extending behind the assistant and project banner before fading at the top of the workspace cards. Its height adjusts with the layout. It uses your browser’s local time: a bay sunrise from 5am–noon, sunny Golden Gate from noon–5pm, and the moonlit coast from 5pm–5am. It checks again when you return to the tab and once a minute while open. No location permission is needed. Customize → Preview background lets you inspect each scene; previews last for this tab session, and new visits use the automatic schedule."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"",headingId:"",text:"Observe dependencies, run browser and service workflows, preserve incident regressions and verify committed patches."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Find dependencies used at runtime",headingId:"find-dependencies-used-at-runtime",text:"Run a reviewed Node application with instrumentation. By default, observed HTTP calls are recorded and blocked before transmission: agenttwin observe -- node app.mjs agenttwin services list --json agenttwin services confirm --host api.stripe.com --decision include agenttwin discover --json A confirmation adds a dependency to inventory; it does not allow requests or install an adapter. To exercise a permitted destination, explicitly pass --allow-host HOST . Observation starts with only PATH and NODE ENV=test ; use repeatable --env-key NAME for environment variables you deliberately want to forward. Request URLs, headers, payloads and application output are omitted from observations. This instruments Node fetch/http/https. Native clients, direct sockets, subprocess traffic and unexercised branches remain outside coverage. It is not an operating-system network sandbox. Discovery also identifies route callbacks and queue handlers as candidates; invocation and business expectations still require review."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Account for every service",headingId:"account-for-every-service",text:"After discovery, run agenttwin services coverage --json . Every application dependency appears with its required operations, available provider subset or real engine, limitations, and the next action for missing coverage. Development tooling is excluded. An available adapter does not make the customer workflow verified, and custom collections do not establish vendor compatibility. Build and validate missing operations before claiming complete workflow coverage."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Use verified provider operations",headingId:"use-verified-provider-operations",text:"Run agenttwin contracts --json for the operation matrix. Stripe's bounded adapter supports customer create/retrieve/list and payment-intent create/retrieve/confirm, with test payment methods, pagination, idempotency and modeled errors. Slack supports its advertised message/channel/history subset. Custom collections support explicitly defined HTTP operations. Official Stripe SDK conformance tests exercise the supported subset. No real charge is made. Subscriptions, refunds, webhooks, broader object fields and unmodeled parameters are not covered. Unsupported behavior returns 501 and makes the test incomplete."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Exercise the application and background work",headingId:"exercise-the-application-and-background-work",text:'A world can include a local browser recipe for a bundled Node server. Install Chromium using npx playwright install chromium from the CLI package directory. Add these fields to a complete reviewed world: { "browser": { "baseUrl": "http://127.0.0.1:4321", "steps": { "action": "goto", "path": "/" }, { "action": "click", "selector": " create-order" }, { "action": "expectText", "selector": " result", "text": "Created" } }, "background": { "service": "orders", "path": "/orders", "count": 1, "timeoutMs": 3000 } } Run with agenttwin run --file agenttwin.world.json --runtime local . The Node server starts, browser actions execute, and the background check waits for matching collection state. Receipts include browser step outcomes and a screenshot when capture succeeds. Browser requests outside the application and configured twins are blocked and recorded as incomplete coverage. Server code still has the local process\'s host access; this is not a VM sandbox. Browser/background recipes currently require local execution. Hosted submissions reject them before queuing a job. Protected Docker approval also returns incomplete for those recipes until its browser runner is implemented. Background checks do not replicate Bull, SQS or arbitrary queue semantics.'},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Trace failures and validate a repair",headingId:"trace-failures-and-validate-a-repair",text:"Service events from local instrumented execution carry application-reported call sites. agenttwin receipt --id RUN ID --json links those events and stack frames to tested source files, checks source freshness, and produces repair hypotheses. These locations guide investigation; they do not prove a root cause. Patch application code and rerun the same fixtures, fault and outcomes. A suggestion is unvalidated until execution proves it against unchanged checks. The dashboard's Recorded steps view shows reported call sites; Technical details shows available browser evidence."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Turn an incident into a permanent regression",headingId:"turn-an-incident-into-a-permanent-regression",text:"Start with a scoped exported incident containing a linked scenario. The repository includes a runnable example in examples/incident-regression . agenttwin incident import --file incident.json --out reviewed-preview.json Review the redacted records and define the intended outcomes in the world. agenttwin regression save --file agenttwin.world.json \\ --id retry safety --incident reviewed-preview.json Redaction preserves matching identities across services. It is heuristic, so review unusual fields and free text before sharing. Import does not connect to production or infer business correctness. Regression definitions are immutable; change their identifier when deliberately changing the contract."},{slug:"stack-loop",title:"From discovery to a verified fix",group:"Use your application",headingText:"Add coding agents and pull requests",headingId:"add-coding-agents-and-pull-requests",text:"agenttwin mcp exposes world lifecycle, incident import, regression saving and protected checks to coding agents. For CI, commit the reviewed regression to a trusted baseline and run: agenttwin regression run \\ --regression .agenttwin/regressions/retry safety.json \\ --revision FULL CANDIDATE SHA --baseline FULL TRUSTED BASELINE SHA \\ --runtime docker --json Checks come from the baseline commit; application files come from the exact candidate commit. The candidate runs in a restricted Docker container without the grading files or Docker socket. Use a reviewed, digest-pinned image through AGENTTWIN RUNNER IMAGE . Docker checks currently support HTTP twins; unsupported infrastructure returns incomplete. Install a customer-repository workflow with separately pinned AgentTwin tooling: agenttwin ci install --tooling-revision FULL REVIEWED AGENTTWIN SHA \\ --regression .agenttwin/regressions/retry safety.json The selected tooling commit must be available on GitHub and contain these commands. The installer creates .github/workflows/agenttwin.yml once, refuses to overwrite a workflow, checks out trusted tooling separately from the application, and fetches the exact candidate commit without executing candidate installation scripts. Configure the reviewed runner image and protect the workflow through repository rules or an organization-required workflow. A template alone cannot make a check mandatory. Local process execution supplies evidence but never grants protected approval. The complete loop is: discover → confirm → prepare → reproduce → patch → rerun unchanged checks → retain the regression on future pull requests."},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"",headingId:"",text:"Use operation contracts, shared scenarios, reusable worlds and coding-agent tools to verify a source fix."},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"Check service support",headingId:"check-service-support",text:"agenttwin contracts --file agenttwin.world.json --json The operation matrix lists endpoints, authentication, state changes, errors and limitations for each configured service. Current adapters are custom JSON collections and a bounded Slack subset. Collection services support GET/list and POST/create with idempotency replay. Slack supports chat.postMessage and conversations.list/history through JSON or form bodies. An unmodeled operation or parameter returns HTTP 501 with X-AgentTwin-Unsupported: true , records an unsupported event and makes the test incomplete. It is never forwarded to a production API. Discovery of a provider does not establish a working twin for that provider."},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"Save a shared scenario",headingId:"save-a-shared-scenario",text:"A scenario supplies the exact starting records across services. Its schema is agenttwin/scenario-v1 ; it contains an id, positive integer version, description, service seeds and optional shared entities. Each entity links selectors that resolve to exactly one seeded record in at least two services. For example, a CRM customer and a Slack support channel can refer to the same customer. agenttwin scenario save --file support.scenario.json --json agenttwin scenario list --json agenttwin scenario show --scenario support retry@1 --json Versions are immutable. Increment the version when fixtures change. Scenario services, adapter types and collection paths must match the world exactly. Receipts include the scenario id, version and content digest. You can also use a saved scenario in a one-shot run: agenttwin run --file agenttwin.world.json --scenario support retry@1 --json"},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"Reuse a world while fixing source",headingId:"reuse-a-world-while-fixing-source",text:"agenttwin world create --file agenttwin.world.json --scenario support retry@1 --ttl 3600 --json agenttwin world run --id WORLD ID --json agenttwin receipt --id RUN ID --json Replace WORLD ID and RUN ID with the returned identifiers. Creation starts a background host and returns loopback service endpoints and fresh test credentials. The lifecycle is provisioning, ready, running and ready again, ending in terminated, expired or failed. Every run stages the current explicitly listed source files and resets service state to the captured baseline. Patch the original source, then run the same world again. Source digests change; the scenario and world specification remain fixed. If you change the specification or scenario, create another world. agenttwin world status --id WORLD ID --json agenttwin world reset --id WORLD ID --json agenttwin world extend --id WORLD ID --ttl 3600 --json agenttwin world teardown --id WORLD ID --json Reset clears mutable state, idempotency keys, events, delayed responses and fault activation. TTL is 1–86400 seconds; expiration closes the endpoints and interrupts active execution. Control requests require a separate token and reject browser origins. Test credentials are stored in private local session metadata; keep them local. Reusable worlds support local HTTP services. They execute Node code on your machine and provide no host network or filesystem isolation. Use one-shot hosted/E2B execution for an isolated workload or PostgreSQL/Redis. World state is held in memory; recreate a world after its host process is lost."},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"Check outcomes and unwanted effects",headingId:"check-outcomes-and-unwanted-effects",text:'Existing assertions describe required final-state counts, optionally filtered by record fields. Add forbiddenEffects to reject particular recorded operations and preservedState to protect seeded records: { "forbiddenEffects": {"id": "no customer write", "service": "crm", "path": "/customers", "operation": "write"} , "preservedState": {"id": "keep customers", "service": "crm", "path": "/customers"} } These are fields added to a complete world specification, not a standalone specification. A forbidden-effect selector can use where ; supported operations are write, read and replay. Filtered effects without a recorded payload fail conservatively as an evidence gap. Preserved-state selectors compare matching records from before and after execution. The receipt\'s evaluation separates taskPassed from safe. An unsafe result fails the run even if every required task assertion passed. Checks include state JSON pointers and event sequence numbers. Dashboard failure explanations and fix prompts include these checks. Unsupported behavior remains incomplete, and execution errors remain errors. agenttwin verify --file .agenttwin/runs/RUN ID/run.json --world agenttwin.world.json --scenario support retry@1 --json agenttwin sync Verification checks current source/specification digests and recomputes local evidence. It does not independently attest execution. Sync uses your existing account connection and sends receipts to your dashboard; scenario storage and reusable lifecycle remain local.'},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"Connect a coding agent",headingId:"connect-a-coding-agent",text:'Start the MCP stdio server from your repository: agenttwin mcp Configure your MCP client with command agenttwin , arguments "mcp" , and the repository as its working directory. The client can discover operation contracts, save/list scenarios, create/list worlds, read status, run a scenario, inspect receipts, reset/extend/teardown a world, and verify a run. The intended sequence is create world → run scenario → inspect run → patch application source → run scenario → verify run. The coding agent performs the patch in the original repository. AgentTwin does not silently rewrite source or weaken tests.'},{slug:"worlds",title:"Reproduce, fix, and retest",group:"Build a test world",headingText:"Try the complete loop",headingId:"try-the-complete-loop",text:"agenttwin example --out ./agenttwin-example agenttwin scenario save --file ./agenttwin-example/support.scenario.json --json agenttwin world create --file ./agenttwin-example/reusable.world.json --scenario support retry@1 --ttl 3600 --json agenttwin world run --id WORLD ID --json The example creates duplicate tickets after a lost response. Inspect its failing receipt, then fix workflow.mjs to use a stable idempotency key on the original request and retry. In this example, replacing the safe flag assignment with const safe = true activates that fix. Rerun the same world: it should contain one ticket and one Slack notification, with unchanged customer records. Keep the specification and scenario intact, verify the new receipt and tear down the world."},{slug:"scenarios",title:"Design reproducible scenarios",group:"Build a test world",headingText:"",headingId:"",text:"Seed linked identities, version fixtures and keep a stable baseline for retests."},{slug:"scenarios",title:"Design reproducible scenarios",group:"Build a test world",headingText:"World versus scenario",headingId:"world-versus-scenario",text:"The world specification defines executable files, command, services, faults and checks. A scenario supplies versioned starting records for those services. The scenario does not replace the application's code or prove provider fidelity. Use a named scenario when several tests need the same customer, order or channel identities. Choose synthetic data that captures the failure conditions. The same identifier alone is not enough: record the relationship and validate that each selector resolves to one record."},{slug:"scenarios",title:"Design reproducible scenarios",group:"Build a test world",headingText:"Complete linked fixture",headingId:"complete-linked-fixture",text:'{ "schema": "agenttwin/scenario-v1", "id": "support customer", "version": 1, "description": "One synthetic customer linked to a support channel", "services": {"name": "crm", "adapter": "json-collection", "collections": {"path": "/customers", "seed": {"id": "customer 1", "channel": "C TEST"} } }, {"name": "slack", "adapter": "slack", "collections": {"path": "/channels", "seed": {"id": "C TEST", "name": "support"} }, {"path": "/messages", "seed": } } , "entities": { "id": "customer 1", "refs": {"service": "crm", "path": "/customers", "where": {"id": "customer 1"}}, {"service": "slack", "path": "/channels", "where": {"id": "C TEST"}} } } The world using this scenario must declare the same services, adapter types and collection paths. Entity references must cover at least two services; zero or multiple matching records are invalid. The shared entity is a validated seed relationship, not automatic ongoing synchronization between unrelated adapters.'},{slug:"scenarios",title:"Design reproducible scenarios",group:"Build a test world",headingText:"Store and reuse",headingId:"store-and-reuse",text:"npx agenttwin scenario save --file support.scenario.json --json npx agenttwin scenario list --json npx agenttwin scenario show --scenario support customer@1 --json npx agenttwin run --file agenttwin.world.json --scenario support customer@1 --json Saving the same version with identical content is repeatable. Saving changed content under that version fails. Increment version when changing seeds, then create a new world for the new baseline. Stored scenarios live under .agenttwin/scenarios/ ; keep the source JSON in version control if the team needs to recreate them elsewhere."},{slug:"scenarios",title:"Design reproducible scenarios",group:"Build a test world",headingText:"Choose useful test data",headingId:"choose-useful-test-data",text:"Start with the smallest fixture that reproduces the incident: one affected identity, the relevant existing records and explicit empty collections for expected new effects. Include boundary conditions deliberately, such as a duplicate key or an existing notification. More synthetic records do not automatically mean better coverage. For a source-fix comparison, keep the same scenario ID, version and digest. For a new business requirement, version the fixture and explain why checks changed. Receipts preserve scenario provenance so these two kinds of comparison can be distinguished. Automatic production-data import, consistent redaction and live cross-service mutation propagation remain additional work. Current fixtures are reviewed files. See reusable worlds for reset and expiry behavior."},{slug:"fidelity",title:"Fidelity contract",group:"Build a test world",headingText:"",headingId:"",text:"Every replica should publish a versioned manifest that labels each operation verified, modeled, or unsupported."},{slug:"fidelity",title:"Fidelity contract",group:"Build a test world",headingText:"What the manifest records",headingId:"what-the-manifest-records",text:"- Provider version the twin was built against. - Fixture source for starting state and seed data. - Last verification date — when the behavior was last compared with reality. - Configuration fields that were captured, and which were not. - State boundaries — what the replica covers and where it ends. - Known differences from the real provider."},{slug:"fidelity",title:"Fidelity contract",group:"Build a test world",headingText:"Evidence, not just a response",headingId:"evidence-not-just-a-response",text:"A passing response cannot hide a bad write. Every run should show: 1. A trace of provider calls and state transitions, in causal order. 2. A before/after state diff across the systems involved. 3. Assertions against final state and invariants , not only the agent's explanation of what it did. The current runtime records operation coverage, source digests, service events and final-state assertions. Custom HTTP collections and the Slack subset have explicit limits; passing their checks does not establish full provider conformance. PostgreSQL and Redis run as real services in the hosted world. Isolated credentials, sanitized records, and disposable execution."},{slug:"safety",title:"Safety and isolation",group:"Build a test world",headingText:"",headingId:"",text:"Current discovery, credential and hosted execution boundaries."},{slug:"safety",title:"Safety and isolation",group:"Build a test world",headingText:"Execution boundary",headingId:"execution-boundary",text:"Application workflows execute in fresh hosted E2B sandboxes, not local containers. The runtime constructs test credentials and an explicit application environment, runs the application as a non-root user, denies new external guest network connections and checks configured final state. Sandbox deletion is requested after execution with a finite TTL backup. Custom HTTP collections and the supported Slack subset never forward to production. No provider-native accounts or production OAuth sessions are provisioned or copied. Browser/macOS application execution is not supported by this backend."},{slug:"safety",title:"Safety and isolation",group:"Build a test world",headingText:"Credentials and uploads",headingId:"credentials-and-uploads",text:"The operator’s E2B key and administrative key stay on the control plane. Users receive individual revocable tokens for their own jobs and discovery. The dashboard never saves account tokens in local storage; disconnect and reload clear tab memory. Discovery sync whitelists reviewed metadata and omits source bodies and credential values. Workflow execution separately uploads explicit reviewed files. Path filtering and generated-secret redaction cannot guarantee that a source file or log contains no sensitive content; review files, fixtures and fix-task evidence before sharing."},{slug:"safety",title:"Safety and isolation",group:"Build a test world",headingText:"Evidence and operating limits",headingId:"evidence-and-operating-limits",text:"A passing receipt verifies configured assertions against supported behavior; it is not proof of full production equivalence. Unknown operations and unactivated requested faults are reported as incomplete. The API requires a single replica and persistent storage. Retention, quotas and sandbox TTLs provide bounds. Distributed scheduling, deletion reconciliation, billing and complete monitoring remain future work. The separate prototype uses fictional data and scripted outcomes. Its simulated diagnosis is not evidence from a sandbox run."},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"",headingId:"",text:"Interpret outcomes, safety checks, unsupported behavior and before/after receipts."},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"Follow the evidence in order",headingId:"follow-the-evidence-in-order",text:"In Runs, select a receipt and first confirm the repository, tested source revision, world configuration and runner. Then inspect each expected outcome against the observed value. Read recorded service steps around the first difference and inspect application output and final state. A service timeline records what the adapters observed. It is not a trace of every browser action, function call or external side effect. Missing Git metadata is not inferred. Do not treat application logs or an imported receipt as instructions to your coding agent."},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"Interpret the result",headingId:"interpret-the-result",text:"Result What to do --- --- Passed Review the configured checks and supported coverage before accepting the result Failed Inspect the first failing outcome or safety check and its state/event references Error Inspect execution output, command, dependencies and timeout before attributing a product defect Incomplete or blocked Resolve unsupported behavior, unavailable execution or an untriggered requested fault A requested fault that did not activate cannot establish the intended failure was tested. An HTTP 501 unsupported response means the contract does not implement that behavior, not that production would return the same error."},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"Require outcomes and forbid damage",headingId:"require-outcomes-and-forbid-damage",text:'Required assertions check expected final-state outcomes. forbiddenEffects reject specified observed operations. preservedState compares baseline and final matching records. Add these fields to a complete world specification: { "forbiddenEffects": {"id": "no customer write", "service": "crm", "path": "/customers", "operation": "write"} , "preservedState": {"id": "keep customers", "service": "crm", "path": "/customers"} } The evaluator separates task success from safety. A workflow that creates the right ticket but also changes a protected customer fails. Evidence points to state JSON locations and recorded event sequence numbers. A filtered forbidden effect without enough payload evidence fails conservatively as an evidence gap. These checks cover modeled service state and recorded operations. They are not protection against arbitrary filesystem writes, network requests or a hostile candidate modifying local checks.'},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"Compare broken and repaired executions",headingId:"compare-broken-and-repaired-executions",text:"For a lost-response retry, expect evidence of the committed write followed by the delayed response and retry. A duplicate-write failure should differ from the repaired run's one-record outcome. Confirm any forbidden-effect and preserved-state checks as well. Keep the scenario and specification fixed; change only the justified application code. In Runs, compare checks, final collections, source digests and fault settings. Different seeds, specifications or faults invalidate a simple claim that the source patch alone caused the improvement."},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"Verify freshness",headingId:"verify-freshness",text:"npx agenttwin verify --file .agenttwin/runs/RUN ID/run.json --world agenttwin.world.json --scenario support retry@1 --json Use the scenario actually used by the run. Verification recomputes local evidence and compares current source/specification provenance. It does not rerun the application or independently attest that a receipt is authentic. Run again after a code change; an old passing receipt is not evidence for new source."},{slug:"evidence",title:"Read evidence and approve a fix",group:"Evidence and reference",headingText:"Share and retain the result",headingId:"share-and-retain-the-result",text:"npx agenttwin sync sends reviewed receipts to the connected account. You can also import run.json in Runs without uploading it. Fix & retest exports an evidence-based coding task; review its proposed change and run the unchanged checks again. Keep the specification, scenario source and receipts alongside the application change where appropriate. Automatic generation of permanent browser regression tests and protected independent grading are not implemented. Troubleshooting covers common evidence gaps."},{slug:"cli",title:"CLI and coding-agent reference",group:"Evidence and reference",headingText:"",headingId:"",text:"Find commands, local artifacts, exit codes and all twelve coding-agent tools."},{slug:"cli",title:"CLI and coding-agent reference",group:"Evidence and reference",headingText:"Run commands from your repository",headingId:"run-commands-from-your-repository",text:"Use npx agenttwin for an installed release, or a built checkout's CLI for checkout-only features. Node.js 22.12+ is required. --json writes structured results to stdout and logs to stderr. Substitute returned IDs for uppercase placeholders. Command Purpose --- --- init Discover dependencies and workflow candidates login Connect the terminal to your dashboard account sync Send reviewed discovery and receipts to that account example --out ./agenttwin-example Generate runnable example source and worlds prepare --file preparation.json Validate mappings and create an explicit application bundle contracts --file agenttwin.world.json --json Inspect adapter operation coverage run --file agenttwin.world.json --json Execute a one-shot local world run --runtime hosted --file agenttwin.world.json Request optional API-managed cloud execution run --runtime e2b --file agenttwin.world.json Use your own configured E2B runtime scenario save --file support.scenario.json --json Validate and save an immutable scenario version scenario list --json List saved versions and digests scenario show --scenario support retry@1 --json Read a saved fixture world create --file agenttwin.world.json --scenario support retry@1 --ttl 3600 --json Start a reusable local HTTP world world list --json List local lifecycle metadata world status --id WORLD ID --json Inspect lifecycle and connection information world run --id WORLD ID --json Reset baseline, stage current listed source and execute world reset --id WORLD ID --json Clear state, keys, events and activated faults world extend --id WORLD ID --ttl 3600 --json Set a ready world's expiry to now plus TTL world teardown --id WORLD ID --json Close services and end the world receipt --id RUN ID --json Inspect recorded checks and a source-fix task verify --file PATH TO RUN JSON --world agenttwin.world.json --json Recompute checks and inspect freshness without execution mcp Serve coding-agent tools over stdio TTL is 1–86400 seconds. Use the optional --scenario id@version on verification when the receipt uses a saved scenario."},{slug:"cli",title:"CLI and coding-agent reference",group:"Evidence and reference",headingText:"Run exit codes",headingId:"run-exit-codes",text:"Code Meaning --- --- 0 Passed 1 Failed or execution error 2 Incomplete or blocked 3 Invalid input Use the receipt's details to distinguish an assertion failure from infrastructure or execution errors. A nonzero result alone is insufficient diagnosis."},{slug:"cli",title:"CLI and coding-agent reference",group:"Evidence and reference",headingText:"Where artifacts live",headingId:"where-artifacts-live",text:"Location Contents --- --- .agenttwin/inventory.json Discovery inventory and candidate metadata .agenttwin/AGENT-TASK.md Repository analysis task for a coding agent .agenttwin/scenarios/ Locally saved immutable scenario versions .agenttwin/runs/ Run receipts and associated evidence Prepared output directory Explicit source files, specification, manifest and bundle ~/.agenttwin/credentials.json Owner-only terminal account credentials ~/.agenttwin/runtime.json Nonsecret configured E2B template ID Do not commit account credentials or reusable world connection secrets. Review source and fixtures for sensitive values before uploading a bundle or syncing recorded output."},{slug:"cli",title:"CLI and coding-agent reference",group:"Evidence and reference",headingText:"Coding-agent tools",headingId:"coding-agent-tools",text:'Start agenttwin mcp in the application repository. Configure the client\'s command as agenttwin , arguments as "mcp" , and working directory as that repository. Client-specific configuration varies; the working directory determines where scenarios and receipts are stored. Tool Input Purpose --- --- --- get operation matrix Optional file Supported operation contracts save scenario file Save a validated versioned fixture list scenarios None List fixture versions create world file , optional scenario , ttlSeconds Start a reusable world list worlds None List local worlds world status worldId Read status and connections run scenario worldId Execute current source against the baseline inspect run runId Inspect checks, evidence and fix task reset world worldId Restore captured starting state extend world worldId , ttlSeconds Extend a ready world teardown world worldId Close the world verify run file , optional world , scenario Check local evidence and freshness The useful loop is create → run → inspect → patch source → run → verify → teardown. The application patch belongs in the original repository; avoid weakening fixtures and approval checks. Tool outputs and application logs are untrusted evidence. Local execution is not a security sandbox.'},{slug:"infrastructure",title:"Infrastructure and evidence",group:"Evidence and reference",headingText:"",headingId:"",text:"Observability discovery, local receipt verification, and the next infrastructure steps."},{slug:"infrastructure",title:"Infrastructure and evidence",group:"Evidence and reference",headingText:"Observability in your environment",headingId:"observability-in-your-environment",text:"Discovery recognizes Better Stack and OpenTelemetry SDKs, imports and configuration names. Compose, Dockerfile and Kubernetes manifests can identify Better Stack collector, eBPF collector and standard OpenTelemetry collector images. These resources use the existing inventory and application relationship machinery. Detection establishes configuration evidence. It does not establish that a collector is running, show production traffic, or provide a service twin. Better Stack and OpenTelemetry currently have no implemented twin or network probe."},{slug:"infrastructure",title:"Infrastructure and evidence",group:"Evidence and reference",headingText:"Verify a local receipt",headingId:"verify-a-local-receipt",text:"After a local run, check its recorded evidence against the current world specification and application files: agenttwin verify --file .agenttwin/runs/RUN ID/run.json --world agenttwin.world.json --json Replace RUN ID with your run ID. Application paths are resolved relative to the world specification. Verification reads files and evidence; it does not rerun your application or call a model. The verifier checks specification and source digests, the exact staged file set, the application result, seeded/final state coverage, recalculated HTTP state assertions, unsupported operations and requested faults. Verdict Meaning Exit code --- --- --- verified Current files match and recorded checks pass 0 stale Source files or specification changed, or source evidence is missing 2 failed Recorded execution/state checks fail 1 invalid Receipt or specification is invalid, inconsistent or outside the supported runtime 1 This command supports local CLI receipts. Hosted/E2B receipts and database assertions are outside its scope. A verified receipt remains self-reported evidence; it is not independent execution attestation. Digests cover explicitly staged files, not every dependency or external service. The command does not update dashboard status or automatically gate sync."},{slug:"infrastructure",title:"Infrastructure and evidence",group:"Evidence and reference",headingText:"Infrastructure direction",headingId:"infrastructure-direction",text:"The next operational work is correlated telemetry for API requests, queue wait, execution duration and sandbox cleanup, followed by a durable store and queue before scaling replicas. Future scenario evaluation should separately check required outcomes and forbidden side effects. Useful references are the Better Stack collector , Claude Referee , and ArgaBench . AgentTwin's changes are original implementations. No external collector or evaluation service was installed by this work."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"",headingId:"",text:"Resolve account, discovery, adapter, execution and verification problems."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Start with the failed boundary",headingId:"start-with-the-failed-boundary",text:"Identify whether the problem is discovery, account connection, preparation, service support, application execution or evidence. Keep the run ID, command, exit code and receipt. Review logs locally and redact sensitive values before sharing them."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"CLI command is missing or Node fails",headingId:"cli-command-is-missing-or-node-fails",text:"Run node --version and inspect the CLI version/help. Node.js 22.12+ is required. In this repository, nvm use selects the checked-in runtime version. A previously published package may lack checkout-only world commands: build and use this repository's CLI rather than assuming the docs describe your old installed package."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Onboarding says the account could not be loaded",headingId:"onboarding-says-the-account-could-not-be-loaded",text:"Use Try again and confirm the configured AgentTwin API is reachable. A running website does not establish that the separate account API is healthy. Check the browser's failed account request and API server logs. Sign in again if the session is unauthorized. Do not change assertions or fixtures to resolve an account failure. Browser appearance preferences can be edited without a loaded account; terminal approval and account project checks require the authenticated account. Dashboard guide explains connection state and refresh."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Discovery finds too much or nothing",headingId:"discovery-finds-too-much-or-nothing",text:"Run init from the actual application root. Inspect recorded source and dependency evidence before accepting a candidate. Use --exclude for unused integrations and rediscover after source changes. Environment keys alone do not create supported adapters. Agent analysis and static discovery produce candidates requiring review."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Preparation rejects a workflow",headingId:"preparation-rejects-a-workflow",text:"Use actual discovery workflow and tool IDs. Include reviewed mappings for every recorded candidate operation. Confirm the entrypoint is built, listed files exist relative to the spec, and the command begins with node . Unsupported SDK operations require additional adapter work or a narrower test, not a fabricated mapping marked reviewed."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Module missing or production requests still occur",headingId:"module-missing-or-production-requests-still-occur",text:"Bundle application dependencies before preparation. The runtime does not install them. Override service base URLs with the generated twin endpoint and use its generated token. Inspect the application client's configuration; changing credentials alone does not redirect a production URL. Local application code has host network access, so review execution paths before running."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"HTTP 501 or incomplete coverage",headingId:"http-501-or-incomplete-coverage",text:"Inspect contracts and the receipt's unsupported event. Unknown methods or parameters are deliberately rejected and are not proxied to production. Current Slack support excludes pagination, threads, files and OAuth. Either stay within the implemented contract or implement and validate the missing adapter operation before claiming coverage."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Requested failure never activated",headingId:"requested-failure-never-activated",text:"Check the application's actual method/path and recorded operations against the fault configuration. Ensure the relevant write was reached and the client has a timeout that exposes the delayed response. An untriggered requested fault makes the intended failure test incomplete. Do not remove the fault merely to obtain a passing result."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Same scenario version cannot be saved",headingId:"same-scenario-version-cannot-be-saved",text:"Versions are immutable. Identical content can be saved again; modified content needs a higher version. Check cross-service references for exactly one matching seeded record. Use a new world for a changed baseline and keep the previous version for comparisons."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"World expired or disappeared",headingId:"world-expired-or-disappeared",text:"Inspect world status . Expiration closes endpoints and interrupts active execution. A world cannot be revived after termination or expiry; create another one. Extend a ready world before its TTL elapses. State is held in the host process's memory and is not recoverable after that process is lost."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Tests pass but the repair is unconvincing",headingId:"tests-pass-but-the-repair-is-unconvincing",text:"Inspect required outcomes, forbidden effects and protected starting records. Confirm the fault activated and that the test actually reached the failing operation. Compare scenario/specification digests and source changes. Add missing meaningful checks as a separately reviewed test change; do not pretend changing checks proves a source-only repair."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Receipt is stale after a patch",headingId:"receipt-is-stale-after-a-patch",text:"Run again. For a prepared one-shot bundle, rebuild and prepare the changed source first. For a reusable world, confirm the listed source files are the ones you edited. Verify the new receipt against current source, world and scenario; verification never executes application code."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Cloud execution is unavailable",headingId:"cloud-execution-is-unavailable",text:"Select cloud execution explicitly only when needed. API-managed cloud jobs require an operator-configured runtime. Direct E2B requires your own key and template setup. A gateway can serve accounts and synced evidence without cloud credentials; that does not mean cloud execution is provisioned. PostgreSQL and Redis worlds require cloud execution today."},{slug:"troubleshooting",title:"Troubleshoot setup and tests",group:"Help and direction",headingText:"Runs is empty",headingId:"runs-is-empty",text:"Discover and run in the intended repository, then connect the terminal and sync. Or import a run.json receipt manually. Manual imports disappear on page reload and are not uploaded. Browser connection tokens stay in page memory; reconnect if needed and use workspace refresh to load account results. For the verified end-to-end path, return to your first verified fix ."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"",headingId:"",text:"Practical answers about discovery, supported execution, accounts and data."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"Can I use AgentTwin now?",headingId:"can-i-use-agenttwin-now",text:"Yes, for explicitly configured bundled Node workflows using supported operations. Run npx agenttwin init with Node.js 22.12+, review discovery, prepare your real files and execute locally against supported HTTP twins, or explicitly choose a cloud sandbox. The dashboard supports individual AgentTwin accounts; users can also configure their own E2B account for direct CLI execution."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"Does it clone my production accounts or every tool?",headingId:"does-it-clone-my-production-accounts-or-every-tool",text:"No. Discovery finds dependency and code signals. Supported services use synthetic state and fresh test credentials. A catalog entry does not imply a working vendor adapter. Provider-native account provisioning and arbitrary production-environment cloning are not implemented."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"Is it only for refunds?",headingId:"is-it-only-for-refunds",text:"No. The product addresses workflows and agent side effects across systems. Four fault classes ship today: timeout-after-write, blackhole (a dependency going dark mid-call), server-error (repeated failures from a dependency) and duplicate-write (first-class duplicate deliveries, suppressed by idempotency keys). Seeded reproduction and named property checks apply across all of them. Refund scenarios are historical examples."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"What happens to credentials and data?",headingId:"what-happens-to-credentials-and-data",text:"The operator’s E2B key stays on the API server. Dashboard account tokens remain in tab memory. Sync sends reviewed metadata, not source bodies or credential values. Execution uploads explicitly reviewed application files and fixtures; those files can themselves contain sensitive values, so review the bundle. No production OAuth session is reused. The terminal CLI keeps its saved login and runtime-template config only under ~/.agenttwin/ and does not scan other dotfiles or shell environments for credentials."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"Are execution sandboxes zero-retention?",headingId:"are-execution-sandboxes-zero-retention",text:"Application sandboxes are created fresh for one run and deleted when it ends (a finite sandbox TTL is the backstop); source is not retained for recovery. What is retained is the evidence: receipts, with recorded events and before/after state, persist in your account (bounded at 30 days and 1,000 receipts per account) — that retention is the product, not an accident. There is no self-service delete-on-request pipeline for stored receipts yet; account revocation blocks new runs but does not erase history today."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"Does init automatically run and repair every workflow?",headingId:"does-init-automatically-run-and-repair-every-workflow",text:"No. Init offers agent-assisted analysis and exports workflow candidates. Inputs, invocation, dependency mappings and assertions need review. Fix & retest exports recorded evidence for your coding agent; a rebuilt bundle and fresh execution are required to verify a repair."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"What is saved in the browser?",headingId:"what-is-saved-in-the-browser",text:"Manual declarations, map layout and preferences persist in browser storage. Imported discovery and receipts stay in memory. Account-owned discovery and jobs persist on the API. Tokens are cleared on disconnect or reload."},{slug:"faq",title:"FAQ",group:"Help and direction",headingText:"Is the prototype a real execution?",headingId:"is-the-prototype-a-real-execution",text:"The separate prototype is scripted and uses fictional scenarios. The dashboard and CLI operate on actual imported/synced discovery and hosted run receipts. Engineering examples are not customer references."},{slug:"wedge",title:"Example: timeout after a write",group:"Help and direction",headingText:"",headingId:"",text:"A historical payment example of a general workflow fault class."},{slug:"wedge",title:"Example: timeout after a write",group:"Help and direction",headingText:"The scenario",headingId:"the-scenario",text:"A worker asks a payment provider to create a refund. The provider commits the write, but the response times out. The worker cannot tell whether the refund happened and retries. A weak implementation creates a second refund. A resilient implementation uses an idempotency key and verifies final state. sequenceDiagram participant W as Worker participant P as Payment provider W- P: Create refund (idempotency key) P- P: Commit refund P--xW: Response lost (timeout) W- P: Retry create refund Note over W,P: Weak: a second refund. Resilient: the key returns the original."},{slug:"wedge",title:"Example: timeout after a write",group:"Help and direction",headingText:"What the scenario declares",headingId:"what-the-scenario-declares",text:"--- --- Starting state One eligible payment, zero refunds. Injected condition Commit refund; discard response; allow retry. Expected outcome Exactly one refund record, one customer notification, a recoverable trace. Regression artifact Versioned starting state, fault point, input, and assertions."},{slug:"wedge",title:"Example: timeout after a write",group:"Help and direction",headingText:"Why this wedge",headingId:"why-this-wedge",text:"- Real — this failure class appears in production integrations, not only in theory. - Costly — a duplicate refund moves money and damages trust. - Hard to reproduce — it needs a write that commits and a response that never arrives. - Testable without risk — a developer should be able to reproduce it without credentials, network calls, or a real account. The CLI runtime supports all four fault classes — timeout-after-write, blackhole, server-error and duplicate-write — across the supported HTTP twins (custom JSON collections, Slack, Stripe, and the thirteen vendored twins). Seeded fault scheduling applies to every class except the declared timeout-after-write delay, which stays the user's declared spec. Hosted sandbox runs accept faults too, but a run seed and seed matrices are currently local-runtime only. Prepare and submit your actual workflow code to inspect the write count and fault activation. A custom collection test does not verify Stripe behavior."},{slug:"wedge",title:"Example: timeout after a write",group:"Help and direction",headingText:"What a reproduced failure buys you",headingId:"what-a-reproduced-failure-buys-you",text:'The fault is seeded: from one seed string, trials deterministically derive which collection faults and how long the response is withheld (plus an unfaulted control trial). Seeds cover fault selection and delays, not OS scheduling. A saved trial becomes a named regression you can require in CI, so the fix is proven against unchanged checks and the failing trial carries a seed coordinate in its receipt. In buyer\'s terms: "first failure at seed 000000008f2c41d9, reproduced exactly" replaces "the refunds double sometimes; we could never reproduce it."'},{slug:"wedge",title:"Example: timeout after a write",group:"Help and direction",headingText:"The seeded fault classes",headingId:"the-seeded-fault-classes",text:"Four fault classes ship today, each named by the loss it costs, never the mechanism. The run seed decides which matched requests get faulted, so the same seed plus the same fingerprint recreates the same schedule: - Timeout after write — the write commits, the answer vanishes mid-charge; a weak retry turns one refund into two. The declared delayMs is application-visible spec, never seeded. - Blackhole — the service goes dark mid-charge; no response at all, ever; the caller never learns whether the write committed. - Server error — the dependency starts returning 500s (seeded rejections and an optional seeded delay window), so error paths get exercised. - Duplicate write — two refunds hit at the same time; duplication itself, not a lost response inviting a retry. An idempotency key suppresses it, which is exactly the property worth asserting. Further fault types are deliberately rejected by today's schemas rather than silently ignored, and an untriggered requested fault makes a run incomplete."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"",headingId:"",text:"Current product stage, next milestones and the evidence needed for customer readiness."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"Available foundations",headingId:"available-foundations",text:"The source includes guided repository discovery and reviewed sharing, reusable test worlds, linked scenarios, explicit outcome checks, replay and protected regression tooling. Stripe and Slack plus thirteen additional provider adapters implement bounded subsets; detecting a provider does not establish compatibility with its full API. Four fault classes exist: timeout after a write, dropped responses, server errors and duplicate writes. Seeded selection and delays, captured-source replay, unchanged-check patch verification and bounded fault shrinking are implemented. These do not control arbitrary operating-system scheduling or guarantee deterministic model responses. The dashboard, account-scoped sync, Google/GitHub/OIDC sign-in code and organization-realm selection are implemented. Live release and enterprise acceptance are verified separately from source and local tests."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"1. Close the release gap",headingId:"1-close-the-release-gap",text:"Version 0.3.8 is published on npm, with CLI/MCP reporting aligned and registry integrity matching the tested tarball. Verify the intended website/API rollout and live authentication acceptance. Done when: a clean installation of npx agenttwin init pairs with the right workspace and shares reviewed discovery; installed/deployed revisions and real authentication acceptance are recorded."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"2. Run one real application workflow",headingId:"2-run-one-real-application-workflow",text:"Confirm a pilot workflow's trigger, invocation, runtime, exact service operations and persisted state. Run the actual application revision with test credentials and seeded records. Customer requirements must define the expected outcome and forbidden side effects. Done when: the supported workflow runs end to end, its coverage is visible, and unsupported behavior produces an incomplete result."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"3. Prove provider correctness",headingId:"3-prove-provider-correctness",text:"Expand adapters around the pilot's required operations. Compare behavior with official SDKs and authorized test accounts, including authentication, pagination, mutations, errors, retries, reset and webhooks where needed. Done when: each required operation has a versioned contract, conformance evidence and explicit limitations. Adapter count alone is not the acceptance criterion."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"4. Turn a real failure into a protected regression",headingId:"4-turn-a-real-failure-into-a-protected-regression",text:"Reproduce a meaningful failure, connect evidence to the failing operation, patch application source and rerun unchanged checks. Save the scenario and install a required pull-request check using a trusted grading baseline. Done when: the original code fails, the fix passes, a deliberately reintroduced defect fails, and candidate changes cannot weaken the grading checks. Protected browser/background and database-backed execution still need broader runner support."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"5. Earn repeated pilot use",headingId:"5-earn-repeated-pilot-use",text:"Make onboarding and evidence understandable, measure setup effort and false positives, and observe teams using the checks across releases. Broaden runtime and provider coverage from actual workflow needs. Done when: a pilot can show measured setup time, useful defects, dependable regression results and repeat use. Synthetic demonstrations and engineering tests do not establish adoption or willingness to pay."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"Enterprise and scaling gates",headingId:"enterprise-and-scaling-gates",text:"Implement and verify required team roles, tenant SSO enforcement, audit evidence, retention/deletion controls, monitoring and backup/restore before promising enterprise readiness. Move the single-instance store and scheduler to a suitable distributed design before scaling replicas. Any security controls required by the first pilot take priority before granting that pilot access. Shared agent memory helps the development team coordinate; it does not replace provider conformance, customer outcome checks or operational evidence. Roadmap order is a priority sequence, not a delivery-date commitment."},{slug:"roadmap",title:"Product roadmap",group:"Help and direction",headingText:"First private application slice",headingId:"first-private-application-slice",text:"On October 19, a local test of the actual calendar-reading function reproduced missed appointments on short paginated responses. The captured original fails; an application-only patch passes unchanged checks; replay still reproduces the original failure. The regression and private source stay local. This proves a calendar-read slice, with a controlled transport returning short pages. It does not establish full scheduling, Bun/SQL execution, live Google conformance or a protected customer PR check. The local protected Docker check also rejects the original calendar bundle and accepts the fixed bundle with unchanged trusted checks, even when the candidate attempts to weaken its own regression definition. Private-repository build and required-check installation remain open. Release candidate f9338a5 passed 361 CLI tests, 17 web tests, the website build and fresh tarball installation. npm published 0.3.8 , and public registry integrity matches the tested tarball. Production health is reachable, but email verification is reported disabled and full live sign-in acceptance remains open. These checks do not close P0 or establish complete pilot readiness."},{slug:"prototype",title:"Explore the browser demo",group:"Help and direction",headingText:"",headingId:"",text:"Walk through the five-step prototype: choose a world, review the replica, run, inject a fault, and read the diagnosis."},{slug:"prototype",title:"Explore the browser demo",group:"Help and direction",headingText:"The five-step walkthrough",headingId:"the-five-step-walkthrough",text:"Pick one of eight illustrative worlds and map its production stack before creating an isolated test environment. See the declared boundaries — what is masked, blocked, or captured — before running anything. Run the workflow against a clean, repeatable starting state. For example, commit a refund but discard the response, so the worker's retry has to be safe. Inspect the failed assertion and state difference, copy the fix prompt, and restore the same starting state for a regression run."},{slug:"prototype",title:"Explore the browser demo",group:"Help and direction",headingText:"Run it locally",headingId:"run-it-locally",text:"The demo is a Next.js route in the same website app. Start the development server from the repository root. cd /path/to/AgentTwin npm ci --prefix web npm run dev Open http://localhost:3000/demo/"},{slug:"prototype",title:"Explore the browser demo",group:"Help and direction",headingText:"What the prototype does not do",headingId:"what-the-prototype-does-not-do",text:"The fix prompt is a handoff for your coding agent or developer, with the observed failure and a suggested change. It does not inspect or patch customer code. The recovery preview uses a second scripted fixture. Refreshing the browser resets all session state. - No credentials are requested and no provider APIs are called. - No customer code is executed or modified. - Company names are potential customer examples, not customers or partners. Stacks, records, and incidents are invented for demonstration. For the current inventory of what exists, see What exists today ."}];var d=n(4558),c=n(2931),l=n(5704);let u=new Set(["the","a","an","and","or","for","of","to","in","on","at","is","are","was","were","be","it","its","you","your","with","that","this","these","those","from","how","do","does","can","i","my","we"]),p=e=>(e.toLowerCase().match(/[a-z0-9]+/g)||[]).filter(e=>e.length>1&&!u.has(e)),h=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=(e,t)=>("index"===e?"/docs/":"/docs/".concat(e,"/"))+(t?"#"+t:""),f="agenttwin:docs-search-recent";function m(){try{let e=JSON.parse(localStorage.getItem(f)||"[]");return Array.isArray(e)?e.filter(e=>"string"==typeof e).slice(0,6):[]}catch(e){return[]}}let w=[{title:"Quickstart",href:"/docs/quickstart/",detail:"Run a real failure end to end"},{title:"CLI and MCP reference",href:"/docs/cli/",detail:"Commands, artifacts, exit codes"},{title:"Troubleshooting",href:"/docs/troubleshooting/",detail:"Fix setup and execution problems"},{title:"FAQ",href:"/docs/faq/",detail:"Accounts, data and boundaries"}],v=null;function y(){if(v)return v;let e=s.filter(e=>e.text).map(e=>{let t=p(e.text),n=new Map,a=new Set(p(e.title)),r=new Set(p(e.headingText)),i=new Set(p(e.slug.replace(/-/g," ")));for(let e of t)n.set(e,(n.get(e)||0)+1);return{chunk:e,tf:n,title:a,heading:r,slug:i,length:t.length}}),t=new Map;for(let{tf:n}of e)for(let e of n.keys())t.set(e,(t.get(e)||0)+1);let n=e.reduce((e,t)=>e+t.length,0)/(e.length||1)||1,a=n=>{let a=t.get(n)||0;return Math.log(1+(e.length-a+.5)/(a+.5))};return v={search:t=>{let r=[...new Set(p(t))];if(!r.length)return[];let i=t.trim().toLowerCase().replace(/\s+/g," ");return e.map(e=>{let t=1.2*(.25+.75*e.length/n),o=0;for(let n of r){let r=a(n),i=e.tf.get(n)||0;o+=2.2*i/(i+t)*r,e.title.has(n)&&(o+=3*r),e.heading.has(n)&&(o+=2*r),e.slug.has(n)&&(o+=1.2*r)}return i.includes(" ")&&(e.chunk.text.toLowerCase().includes(i)&&(o+=6),e.chunk.title.toLowerCase().includes(i)&&(o+=8),e.chunk.headingText.toLowerCase().includes(i)&&(o+=4)),{entry:e,score:o}}).filter(e=>e.score>.35).sort((e,t)=>t.score-e.score).slice(0,24).map(e=>e.entry.chunk)}}}function x(e,t){let n=s.find(e=>e.slug===t.slug&&!e.headingText),a=t=>{let n=t.toLowerCase(),a=p(e).map(e=>n.indexOf(e)).filter(e=>e>=0);return a.length?Math.min(...a):-1},r=t.text,i=a(r);if(i<0&&n&&(i=a(r=n.text)),i<0)return((null==n?void 0:n.text)||t.text).slice(0,160);let o=Math.max(0,i-60),d=r.slice(o,o+170).trim();return(o>0?"… ":"")+d+(o+170<r.length?" …":"")}function b(e){let{text:t,terms:n}=e;if(!n.length||!t)return(0,r.jsx)(r.Fragment,{children:t});let a=RegExp("(".concat(n.map(h).join("|"),")"),"gi"),i=t.split(a);return(0,r.jsx)(r.Fragment,{children:i.map((e,t)=>t%2==1?(0,r.jsx)("mark",{children:e},t):(0,r.jsx)("span",{children:e},t))})}let k=null!=(a=l.env.NEXT_PUBLIC_AGENTTWIN_API_URL)?a:"https://api.agenttwin.si",T=/\[([a-z0-9][a-z0-9_#/-]{0,79})\]/gi,I=(()=>{let e=0,t=new Map;return n=>{let a=t.get(n);return a||(a="cite-".concat(e++,"-").concat(n.replace(/[^a-z0-9_-]/gi,"-")),t.set(n,a)),a}})();function j(e){let{passages:t,pending:n,sources:a}=e;return(0,r.jsx)("ul",{className:n?"docs-ask-passages is-pending":"docs-ask-passages",children:t.map(e=>(0,r.jsx)("li",{id:a?"docs-".concat(I(e.id)):void 0,children:(0,r.jsxs)("a",{href:e.href,children:[(0,r.jsx)("strong",{children:e.title}),e.heading!==e.title&&(0,r.jsxs)("span",{children:[" › ",e.heading]}),(0,r.jsx)("span",{className:"docs-passage-text",children:e.text})]})},e.href))})}function S(e){let{open:t,onOpenChange:n}=e,[a,s]=(0,i.useState)("search"),[l,u]=(0,i.useState)(""),[h,v]=(0,i.useState)([]),[j,S]=(0,i.useState)(0),[R,A]=(0,i.useState)({kind:"idle"}),D=(0,i.useRef)(null),E=(0,i.useRef)(null),P=(0,i.useRef)(null),N=(0,i.useRef)(null),L=(0,i.useRef)(!1),q=(0,i.useRef)(""),M=(0,i.useCallback)(()=>{var e;null==(e=N.current)||e.abort(),n(!1)},[n]);(0,i.useEffect)(()=>{let e=e=>{if(document.querySelector(".docs-sidebar.is-open"))return;let t=e.target,a=(null==t?void 0:t.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(null==t?void 0:t.tagName);("k"===e.key.toLowerCase()&&(e.metaKey||e.ctrlKey)||"/"===e.key&&!a)&&(e.preventDefault(),n("search"))};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[n]),(0,i.useEffect)(()=>{var e,n,a,r;let i=L.current;if(L.current=t,!1===t){q.current&&(document.body.style.overflow=q.current,q.current=""),null==(n=D.current)||n.close();return}s(t),!1===i&&(q.current=document.body.style.overflow,document.body.style.overflow="hidden",null==(a=D.current)||a.showModal()),null==(e=null!=(r=("ask"===t?P:E).current)?r:E.current)||e.focus()},[t]),(0,i.useEffect)(()=>()=>{var e;return null==(e=N.current)?void 0:e.abort()},[]);let O=(0,i.useMemo)(()=>[...new Set(p(l))],[l]),H=(0,i.useMemo)(()=>l.trim()?y().search(l).map(e=>({chunk:e,snippet:x(l,e)})):[],[l]);(0,i.useEffect)(()=>S(0),[l,a]),(0,i.useEffect)(()=>{var e,t;null==(t=D.current)||null==(e=t.querySelector('[data-result="'.concat(j,'"]')))||e.scrollIntoView({block:"nearest"})},[j]),(0,i.useEffect)(()=>{!1!==t&&v(m())},[t]);let U=(0,i.useCallback)(e=>{if(!e)return void window.scrollTo({top:0,behavior:"smooth"});let t=document.getElementById(e);t&&(t.scrollIntoView({block:"start",behavior:"smooth"}),t.classList.remove("docs-flash-target"),t.offsetWidth,t.classList.add("docs-flash-target"),window.setTimeout(()=>t.classList.remove("docs-flash-target"),900))},[]),F=(0,i.useCallback)(e=>{!function(e){let t=e.trim();if(t.length<2)return;let n=[t,...m().filter(e=>e.toLowerCase()!==t.toLowerCase())].slice(0,6);try{localStorage.setItem(f,JSON.stringify(n))}catch(e){}}(l),M();let t="index"===e.slug?"/docs/":"/docs/".concat(e.slug,"/");if(window.location.pathname===t){U(e.headingId),e.headingId&&(window.location.hash=e.headingId);return}if(e.headingId)try{sessionStorage.setItem("agenttwin:docs-flash",e.headingId)}catch(e){}window.location.assign(g(e.slug,e.headingId))},[M,U,l]);(0,i.useEffect)(()=>{let e=(()=>{try{return sessionStorage.getItem("agenttwin:docs-flash")}catch(e){return null}})();if(!e)return;try{sessionStorage.removeItem("agenttwin:docs-flash")}catch(e){}let t=requestAnimationFrame(()=>window.setTimeout(()=>U(e),80));return()=>cancelAnimationFrame(t)},[U]);let W=(0,i.useCallback)(async e=>{var t;let n=e.trim();if(!n)return;let a=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:6;return y().search(e).slice(0,t).map((t,n)=>({id:"".concat(t.slug,"#").concat(t.headingId||"p".concat(n)).slice(0,80),title:t.title,heading:t.headingText||t.title,href:g(t.slug,t.headingId),text:x(e,t).slice(0,700)}))}(n);A({kind:"loading",passages:a});let r=new AbortController;null==(t=N.current)||t.abort(),N.current=r;try{let e=await fetch("".concat(k,"/v1/ai/search"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({question:n,passages:a.map(e=>{let{id:t,title:n,heading:a,href:r,text:i}=e;return{id:t,title:n,heading:a,snippet:i,url:r}})}),signal:r.signal});if(!e.ok)throw Error(String(e.status));let t=await e.json();if("string"!=typeof t.answer||!t.answer.trim())throw Error("no answer");A({kind:"answer",passages:a,html:function(e){let t=d.xI.parse(e,{async:!1}).replace(T,(e,t)=>'<a href="#'.concat(I(t),'" data-cite="').concat(t,'"><sup>[').concat(t,"]</sup></a>"));return c.A.sanitize(t)}(t.answer)})}catch(e){if((null==e?void 0:e.name)==="AbortError")return;A({kind:"unavailable",passages:a})}},[]),B="search"===a&&!l.trim();return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("button",{type:"button","aria-label":"Search documentation",className:"docs-search-trigger",onClick:()=>n("search"),children:[(0,r.jsx)(o.I,{name:"search"}),(0,r.jsx)("span",{children:"Search documentation"}),(0,r.jsx)("kbd",{children:"⌘ K"})]}),(0,r.jsx)("dialog",{ref:D,className:"docs-search-dialog","aria-label":"Documentation search and AI answers",onCancel:M,onClose:M,onClick:e=>{e.target===e.currentTarget&&M()},children:(0,r.jsxs)("div",{className:"docs-search-dialog-content",children:[(0,r.jsxs)("div",{className:"docs-search-input",children:["ask"===a?(0,r.jsx)(o.I,{name:"sparkles",className:"docs-spark"}):(0,r.jsx)(o.I,{name:"search"}),"search"===a?(0,r.jsx)("input",{ref:E,type:"text",placeholder:"Search pages, commands, and concepts…","aria-label":"Search documentation",value:l,onChange:e=>u(e.target.value),onKeyDown:e=>{if("ArrowDown"===e.key)e.preventDefault(),S(e=>Math.min(e+1,H.length-1));else if("ArrowUp"===e.key)e.preventDefault(),S(e=>Math.max(0,e-1));else if("Enter"===e.key){var t;let n=null==(t=H[j])?void 0:t.chunk;n&&(e.preventDefault(),F(n))}else"Escape"===e.key&&(e.preventDefault(),M())}}):(0,r.jsx)("textarea",{ref:P,rows:2,placeholder:"Ask anything about AgentTwin, e.g. how do I verify a patch?","aria-label":"Ask the documentation",value:l,onChange:e=>u(e.target.value),onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),W(l))}}),(0,r.jsxs)("div",{className:"docs-search-tabs",role:"tablist","aria-label":"Search mode",children:[(0,r.jsx)("button",{type:"button",role:"tab","aria-selected":"search"===a,onClick:()=>s("search"),children:"Search"}),(0,r.jsxs)("button",{type:"button",role:"tab","aria-selected":"ask"===a,onClick:()=>s("ask"),children:[(0,r.jsx)(o.I,{name:"sparkles"}),"Ask AI"]})]}),(0,r.jsx)("button",{type:"button","aria-label":"Close",onClick:M,children:(0,r.jsx)("kbd",{children:"Esc"})})]}),B&&(0,r.jsxs)("div",{className:"docs-search-list docs-search-welcome","aria-live":"polite",children:[h.length>0&&(0,r.jsxs)("div",{className:"docs-recent",children:[(0,r.jsx)("p",{className:"docs-search-caption",children:"Recent searches"}),h.map(e=>(0,r.jsxs)("button",{type:"button",className:"docs-recent-item",onClick:()=>u(e),children:[(0,r.jsx)(o.I,{name:"history"}),(0,r.jsx)("span",{children:e})]},e)),(0,r.jsxs)("button",{type:"button",className:"docs-recent-clear",onClick:()=>{try{localStorage.removeItem(f)}catch(e){}v([])},children:[(0,r.jsx)(o.I,{name:"close"}),"Clear recent searches"]})]}),(0,r.jsx)("p",{className:"docs-search-caption",children:"Explore documentation"}),w.map(e=>(0,r.jsxs)("a",{href:e.href,onClick:M,children:[(0,r.jsx)(o.I,{name:"book-open"}),(0,r.jsxs)("div",{children:[(0,r.jsx)("strong",{children:e.title}),(0,r.jsx)("span",{children:e.detail})]})]},e.href))]}),!B&&"search"===a&&(0,r.jsxs)("div",{className:"docs-search-list","aria-live":"polite",children:[(0,r.jsx)("p",{className:"docs-search-caption",children:H.length?"Results for “".concat(l.trim(),"”"):"No results"}),!H.length&&(0,r.jsxs)("p",{className:"docs-search-empty",children:["No matches for “",l.trim(),"”. Try a command like ",(0,r.jsx)("code",{children:"agenttwin init"})," or a topic like scenarios, or"," ",(0,r.jsx)("button",{type:"button",onClick:()=>s("ask"),children:"ask AI instead"}),"."]}),H.map((e,t)=>{let{chunk:n,snippet:a}=e;return(0,r.jsxs)("a",{href:g(n.slug,n.headingId),"data-result":t,className:j===t?"is-selected":"","aria-current":j===t?"true":void 0,onClick:e=>{e.preventDefault(),F(n)},children:[(0,r.jsx)(o.I,{name:n.headingText?"layout":"book-open"}),(0,r.jsxs)("div",{children:[(0,r.jsxs)("strong",{children:[n.title,n.headingText&&(0,r.jsxs)("span",{className:"docs-hit-heading",children:[" › ",n.headingText]})]}),(0,r.jsx)("span",{children:(0,r.jsx)(b,{text:a,terms:O})})]}),(0,r.jsx)("span",{className:"docs-hit-jump","aria-hidden":"true",children:"↵"})]},n.slug+"|"+n.headingId)})]}),"ask"===a&&(0,r.jsx)(C,{state:R,query:l,onSubmit:e=>{e.preventDefault(),W(l)},onReset:()=>{var e;null==(e=N.current)||e.abort(),A({kind:"idle"}),u("")}}),(0,r.jsxs)("div",{className:"docs-search-help",children:[(0,r.jsx)("span",{children:"↑ ↓ to navigate"}),(0,r.jsx)("span",{children:"↵ to open"}),(0,r.jsx)("span",{children:"esc to close"})]})]})})]})}function C(e){let{state:t,query:n,onSubmit:a,onReset:i}=e;return(0,r.jsxs)("div",{className:"docs-search-list docs-ask-panel","aria-live":"polite",children:[(0,r.jsxs)("form",{className:"docs-ask-form",onSubmit:a,children:[(0,r.jsxs)("button",{type:"submit",className:"docs-ask-submit",disabled:!n.trim(),children:[(0,r.jsx)(o.I,{name:"sparkles"}),"loading"===t.kind?"Asking…":"Ask"]}),(0,r.jsx)("span",{className:"docs-ask-hint",children:"Enter to ask \xb7 Shift+Enter for a new line"}),"idle"!==t.kind&&(0,r.jsx)("button",{type:"button",className:"docs-ask-reset",onClick:i,children:"New question"})]}),"loading"===t.kind&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("p",{className:"docs-ask-status docs-ask-loading",role:"status",children:["Reading the docs",(0,r.jsx)("span",{className:"docs-ask-dots","aria-hidden":"true"})]}),(0,r.jsx)(j,{passages:t.passages,pending:!0})]}),"answer"===t.kind&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("article",{className:"docs-ask-answer",onClick:e=>{let t=e.target.closest("[data-cite]");if(!t)return;e.preventDefault();let n=document.getElementById("docs-ask-passage-".concat(t.dataset.cite));n&&(n.scrollIntoView({block:"nearest",behavior:"smooth"}),n.classList.add("docs-passage-focus"),window.setTimeout(()=>n.classList.remove("docs-passage-focus"),1200))},dangerouslySetInnerHTML:{__html:t.html}}),(0,r.jsx)(j,{passages:t.passages,sources:!0})]}),"unavailable"===t.kind&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("p",{className:"docs-ask-status",children:"The assistant is unavailable right now. Try again shortly."}),t.passages.length>0&&(0,r.jsx)(j,{passages:t.passages})]})]})}function R(e){let{tab:t="search"}=e,[n,a]=(0,i.useState)(!1);return(0,r.jsxs)(r.Fragment,{children:[!1!==n&&(0,r.jsx)(S,{open:n,onOpenChange:a}),(0,r.jsx)("button",{type:"button",onClick:()=>a(t),"aria-haspopup":"dialog","aria-expanded":!1!==n,className:"inline-flex h-9 w-full items-center gap-2 rounded-lg border border-fd-border bg-fd-muted/50 px-3 text-sm text-fd-muted-foreground transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground",children:"ask"===t?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.I,{name:"sparkles"}),(0,r.jsx)("span",{className:"flex-1 text-left",children:"Ask AI"})]}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.I,{name:"search"}),(0,r.jsx)("span",{className:"flex-1 text-left",children:"Search docs…"}),(0,r.jsx)("kbd",{className:"bg-fd-muted px-1.5 py-0.5 text-xs font-normal",children:"⌘K"})]})})]})}}},e=>{e.O(0,[2824,7772,3050,8441,1255,7358],()=>e(e.s=2782)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9352],{3845:()=>{},7815:(e,n,a)=>{"use strict";a.d(n,{default:()=>l});var s=a(5155),r=a(2115);let i=[{href:"/#worlds",label:"Worlds"},{href:"/#how",label:"How it works"},{href:"/#failures",label:"Failures"},{href:"/#pricing",label:"Pricing"},{href:"/enterprise/",label:"Enterprise"},{href:"/docs/",label:"Docs"}];function l(){let[e,n]=(0,r.useState)(!1),a=(0,r.useRef)(null),l=(0,r.useRef)(null);return(0,r.useEffect)(()=>{let e=e=>{var s,r;"Escape"===e.key&&(null==(s=l.current)?void 0:s.querySelector("#navlinks.is-open"))&&(n(!1),null==(r=a.current)||r.focus())},s=e=>{var a;(null==(a=l.current)?void 0:a.contains(e.target))||n(!1)},r=matchMedia("(min-width: 1024px)"),i=()=>n(!1);return document.addEventListener("keydown",e),document.addEventListener("click",s),r.addEventListener("change",i),()=>{document.removeEventListener("keydown",e),document.removeEventListener("click",s),r.removeEventListener("change",i)}},[]),(0,s.jsxs)("header",{className:"site-header",ref:l,children:[(0,s.jsxs)("a",{className:"brand",href:"/","aria-label":"AgentTwin home",children:[(0,s.jsx)("img",{src:"assets/logo/mark-twin-rings.svg?v=white-rings",alt:"",width:29,height:29}),"AgentTwin"]}),(0,s.jsxs)("nav",{className:"main-nav".concat(e?" is-open":""),id:"navlinks","aria-label":"Main navigation",children:[i.map(e=>(0,s.jsx)("a",{href:e.href,onClick:()=>n(!1),children:e.label},e.href)),(0,s.jsx)("a",{className:"nav-mobile-dashboard",href:"/dashboard/",onClick:()=>n(!1),children:"Open dashboard"})]}),(0,s.jsxs)("div",{className:"nav-actions",children:[(0,s.jsx)("a",{href:"/login/",children:"Sign in"}),(0,s.jsxs)("a",{className:"button button-white button-small",href:"/signup/",children:["Get started ",(0,s.jsx)("span",{"aria-hidden":"true",children:"\xbb"})]})]}),(0,s.jsxs)("button",{className:"menu-toggle",ref:a,type:"button","aria-label":e?"Close menu":"Open menu","aria-expanded":e,"aria-controls":"navlinks",onClick:()=>n(!e),children:[(0,s.jsx)("span",{}),(0,s.jsx)("span",{})]})]})}},9081:(e,n,a)=>{Promise.resolve().then(a.bind(a,7815)),Promise.resolve().then(a.t.bind(a,3845,23))}},e=>{e.O(0,[7502,8441,1255,7358],()=>e(e.s=9081)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7177],{1681:()=>{},4057:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,1681,23))}},e=>{e.O(0,[4394,8441,1255,7358],()=>e(e.s=4057)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[879,4520],{9536:(e,s,_)=>{Promise.resolve().then(_.bind(_,6787))}},e=>{e.O(0,[3935,6787,8441,1255,7358],()=>e(e.s=9536)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9566],{2039:(e,t,s)=>{Promise.resolve().then(s.bind(s,8109))},6184:()=>{},8109:(e,t,s)=>{"use strict";s.d(t,{default:()=>j});var n=s(5155),a=s(2115),r=s(6787);function i(e){var t,s,n,a,r;return{company:null!=(t=null==e?void 0:e.company)?t:"",website:null!=(s=null==e?void 0:e.website)?s:"",role:null!=(n=null==e?void 0:e.role)?n:"",teamSize:null!=(a=null==e?void 0:e.teamSize)?a:"",useCase:null!=(r=null==e?void 0:e.useCase)?r:""}}s(1261),s(6184),s(9022);let o={company:"",website:"",role:"",teamSize:"",useCase:""},l="agenttwin:pending-terminal:v1",c="agenttwin:workspace-preferences:v1",d={morning:"bay-morning.png",afternoon:"golden-gate-afternoon.png",evening:"moonlit-coast.png"},u=["Your profile","Your workspace","Connect your application"],p={artwork:"afternoon",compact:!1,autoRefresh:!0,reduceMotion:!1};function h(){return(0,n.jsx)("span",{"aria-hidden":"true",children:"→"})}function m(){return(0,n.jsx)("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:(0,n.jsx)("path",{d:"m4 8 2.5 2.5L12 5",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round"})})}function j(){var e;let[t,s]=(0,a.useState)(null),[j,x]=(0,a.useState)(""),[g,v]=(0,a.useState)(0),[y,w]=(0,a.useState)(0),[f,b]=(0,a.useState)(0),[k,C]=(0,a.useState)(p),[N,S]=(0,a.useState)(""),[A,T]=(0,a.useState)(""),[O,E]=(0,a.useState)(""),[L,F]=(0,a.useState)(o),[P,R]=(0,a.useState)(!1),I=(e,t)=>F(s=>({...s,[e]:t})),[W,z]=(0,a.useState)(""),[M,Y]=(0,a.useState)(!1),[J,D]=(0,a.useState)(!1),[U,_]=(0,a.useState)(!1),[B,q]=(0,a.useState)(""),[H,K]=(0,a.useState)(!1),[V,$]=(0,a.useState)(""),[G,Q]=(0,a.useState)([]),[X,Z]=(0,a.useState)(!1),[ee,et]=(0,a.useState)(""),[es,en]=(0,a.useState)(!1),ea=(0,a.useRef)(null),er="auto"===k.artwork?"afternoon":k.artwork;function ei(e){w(e),b(t=>Math.max(t,e)),S(""),requestAnimationFrame(()=>{var e;return null==(e=ea.current)?void 0:e.focus({preventScroll:!0})})}function eo(){try{let e={};try{let t=JSON.parse(localStorage.getItem(c)||"{}");t&&"object"==typeof t&&!Array.isArray(t)&&(e=t)}catch(e){}return localStorage.setItem(c,JSON.stringify({...e,...k,name:O.slice(0,40),userName:A.slice(0,60)})),en(!1),!0}catch(e){return en(!0),S("Browser storage is unavailable. Your preferences could not be saved."),!1}}async function el(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!t||P)return!1;R(!0),S("");try{let t=await fetch(r.n+"/v1/auth/profile",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({name:A,workspace:O,...i(L),complete:e}),signal:AbortSignal.timeout(15e3)}),n=await t.json();if(!t.ok)throw Error(404===t.status?"Account setup is not available on this API yet. Please try again after the API is updated.":n.error||"Could not save your details. Try again.");return s(n.user),!0}catch(e){return S(e instanceof Error?e.message:"Could not save your details. Try again."),!1}finally{R(!1)}}async function ec(){!t||M||H||P||await el(!0)&&(eo(),location.assign(G.length?"/dashboard/#environment":"/dashboard/#home"))}async function ed(e){if(e.preventDefault(),!M&&!J&&t){Y(!0),q("");try{let e=await fetch(r.n+"/v1/auth/device/approve",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({userCode:W.trim().toUpperCase()}),signal:AbortSignal.timeout(15e3)}),t=await e.json();if(!e.ok)throw Error(t.error||"Could not connect your terminal. Try again.");try{sessionStorage.removeItem(l)}catch(e){}D(!0),z(""),q("Terminal connected. Keep init running; it will sync your project automatically.")}catch(e){q(e instanceof Error?e.message:"Could not connect your terminal.")}finally{Y(!1)}}}async function eu(){if(!H&&t){K(!0),$("");try{let e=await fetch(r.n+"/v1/projects",{credentials:"include",signal:AbortSignal.timeout(15e3)});if(!e.ok)throw Error("Could not check your projects. Try again.");let t=await e.json();if(!Array.isArray(t.projects))throw Error("Could not load your projects. Try again.");Q(t.projects),Z(!0),$(t.projects.length?"Your project is in your workspace.":"Running init discovers files locally. Connect this terminal and keep init running until it confirms the project is synced.")}catch(e){$(e instanceof Error?e.message:"Could not check your projects.")}finally{K(!1)}}}async function ep(e){try{await navigator.clipboard.writeText(e),et(e),S("Command copied. Run it in your project’s terminal.")}catch(e){S("Select the command and copy it into your terminal.")}}return(0,a.useEffect)(()=>{let e=new URLSearchParams(location.hash.slice(1)).get("user_code"),t=null;try{e&&/^[A-F0-9]{10}$/.test(e)?(t={code:e,expires:Date.now()+6e5},sessionStorage.setItem(l,JSON.stringify(t))):t=JSON.parse(sessionStorage.getItem(l)||"null")}catch(s){e&&(t={code:e,expires:Date.now()+6e5})}if(t&&/^[A-F0-9]{10}$/.test(t.code||"")&&Number(t.expires)>Date.now())z(t.code),_(!0),w(2),b(2);else try{sessionStorage.removeItem(l)}catch(e){}e&&history.replaceState(null,"",location.pathname+location.search)},[]),(0,a.useEffect)(()=>{try{let e=JSON.parse(localStorage.getItem(c)||"null");e&&C({artwork:"afternoon",compact:!0===e.compact,autoRefresh:!1!==e.autoRefresh,reduceMotion:!0===e.reduceMotion})}catch(e){}},[]),(0,a.useEffect)(()=>{let e=new AbortController;return x(""),fetch(r.n+"/v1/auth/me",{credentials:"include",signal:AbortSignal.any([e.signal,AbortSignal.timeout(15e3)])}).then(async e=>{var t;if(401===e.status)return void location.replace("/login/?next=onboarding");if(!e.ok)throw Error();let n=(await e.json()).user;s(n),T(n.name),E(n.workspace),F(i(n.workspaceProfile)),(null==(t=n.workspaceProfile)?void 0:t.completedAt)&&(w(2),b(2))}).catch(()=>{e.signal.aborted||x("Your account could not be loaded. Try again to continue setup.")}),()=>e.abort()},[g]),(0,a.useEffect)(()=>{if(!t)return;let e=new AbortController,s=!1,n=async()=>{if("hidden"!==document.visibilityState&&!s){s=!0;try{let t=await fetch(r.n+"/v1/projects",{credentials:"include",signal:AbortSignal.any([e.signal,AbortSignal.timeout(1e4)])});if(!t.ok)return;let s=await t.json();!e.signal.aborted&&Array.isArray(s.projects)&&(Q(s.projects),Z(!0),s.projects.length&&$("Your project is in your workspace."))}catch(e){}finally{s=!1}}};n();let a=2===y?setInterval(()=>{n()},3e3):void 0;return document.addEventListener("visibilitychange",n),()=>{e.abort(),clearInterval(a),document.removeEventListener("visibilitychange",n)}},[y,null==t?void 0:t.email]),(0,n.jsxs)("main",{className:"onboarding-page onboarding-san-francisco".concat(k.reduceMotion?" onboarding-still":""),style:{"--setup-scene":"url('assets/dashboard/".concat(d[er],"')")},children:[(0,n.jsx)("div",{className:"onboarding-backdrop","aria-hidden":"true"}),(0,n.jsxs)("section",{className:"onboarding-shell","aria-labelledby":"onboarding-title",children:[(0,n.jsxs)("header",{className:"onboarding-header",children:[(0,n.jsxs)("a",{className:"auth-brand",href:"/","aria-label":"AgentTwin home",children:[(0,n.jsx)("img",{src:"assets/logo/mark-twin-rings.svg",width:"26",height:"26",alt:""}),"AgentTwin"]}),(0,n.jsxs)("a",{href:"/docs/workflow/",children:["Need a hand? ",(0,n.jsx)(h,{})]})]}),(0,n.jsxs)("div",{className:"onboarding-content".concat(0===y?" onboarding-welcome":""),children:[(0,n.jsxs)("div",{className:"onboarding-controls",children:[(0,n.jsxs)("div",{className:"onboarding-greeting",children:[(0,n.jsx)("p",{children:O||"Your workspace"}),(0,n.jsx)("h1",{id:"onboarding-title",children:t?"Welcome, ".concat(t.name.trim().split(/\s+/)[0],"."):"Set up your workspace."})]}),!t&&!j&&(0,n.jsx)("p",{className:"setup-help",role:"status",children:"Loading your account…"}),j&&(0,n.jsxs)("div",{className:"onboarding-account-error",role:"alert",children:[(0,n.jsx)("p",{children:j}),(0,n.jsx)("button",{type:"button",onClick:()=>v(e=>e+1),children:"Try again"})]}),(0,n.jsx)("ol",{className:"setup-steps","aria-label":"Workspace setup",children:u.map((e,s)=>{var a,r;return(0,n.jsxs)("li",{className:"setup-step".concat(y===s?" active":"").concat(s<f?" visited":""),children:[(0,n.jsx)("h2",{children:(0,n.jsxs)("button",{type:"button",ref:y===s?ea:void 0,className:"setup-step-heading",onClick:()=>ei(s),disabled:s>f||M||H||P||!t,"aria-expanded":y===s,"aria-controls":"setup-panel-".concat(s),"aria-current":y===s?"step":void 0,children:[(0,n.jsx)("span",{className:"setup-step-number",children:s<f&&s!==y?(0,n.jsx)(m,{}):s+1}),e,s<f&&s!==y&&(0,n.jsx)("span",{className:"setup-edit",children:"Edit"})]})}),(0,n.jsxs)("div",{id:"setup-panel-".concat(s),className:"setup-step-panel",hidden:y!==s,children:[0===s&&(0,n.jsxs)("form",{className:"setup-profile-form",onSubmit:async e=>{e.preventDefault(),await el()&&ei(1)},children:[(0,n.jsx)("p",{children:"Tell your team who you are."}),(0,n.jsxs)("label",{htmlFor:"setup-name",children:["Full name",(0,n.jsx)("input",{id:"setup-name",autoComplete:"name",value:A,onChange:e=>T(e.target.value),maxLength:100,required:!0,disabled:!t||P})]}),(0,n.jsxs)("label",{htmlFor:"setup-email",children:["Account email",(0,n.jsx)("input",{id:"setup-email",type:"email",value:(null==t?void 0:t.email)||"",readOnly:!0,autoComplete:"email"})]}),(0,n.jsxs)("label",{htmlFor:"setup-role",children:["Job title ",(0,n.jsx)("span",{children:"Optional"}),(0,n.jsx)("input",{id:"setup-role",autoComplete:"organization-title",value:L.role,onChange:e=>I("role",e.target.value),maxLength:100,disabled:!t||P,placeholder:"e.g. Platform engineer"})]}),(0,n.jsxs)("button",{type:"submit",className:"setup-primary",disabled:!t||P,children:[P?"Saving…":"Continue"," ",(0,n.jsx)(h,{})]})]}),1===s&&(0,n.jsxs)("form",{className:"setup-profile-form",onSubmit:async e=>{e.preventDefault(),await el()&&(eo(),ei(2))},children:[(0,n.jsx)("p",{children:"Name the workspace for your application and test results."}),(0,n.jsxs)("label",{htmlFor:"setup-workspace",children:["Workspace name",(0,n.jsx)("input",{id:"setup-workspace",value:O,onChange:e=>E(e.target.value),required:!0,maxLength:100,disabled:!t||P,placeholder:"e.g. Acme engineering"})]}),(0,n.jsxs)("label",{htmlFor:"setup-company",children:["Organization ",(0,n.jsx)("span",{children:"Optional"}),(0,n.jsx)("input",{id:"setup-company",autoComplete:"organization",value:L.company,onChange:e=>I("company",e.target.value),maxLength:100,disabled:!t||P})]}),(0,n.jsxs)("label",{htmlFor:"setup-website",children:["Company website ",(0,n.jsx)("span",{children:"Optional"}),(0,n.jsx)("input",{id:"setup-website",type:"url",autoComplete:"url",value:L.website,onChange:e=>I("website",e.target.value),maxLength:254,placeholder:"https://example.com",disabled:!t||P})]}),(0,n.jsxs)("label",{htmlFor:"setup-size",children:["Team size ",(0,n.jsx)("span",{children:"Optional"}),(0,n.jsxs)("select",{id:"setup-size",value:L.teamSize,onChange:e=>I("teamSize",e.target.value),disabled:!t||P,children:[(0,n.jsx)("option",{value:"",children:"Select team size"}),["1","2–10","11–50","51–200","201–1000","1000+"].map(e=>(0,n.jsx)("option",{value:e,children:"1"===e?"Just me":e+" people"},e))]})]}),(0,n.jsxs)("label",{htmlFor:"setup-use",children:["What do you want to test? ",(0,n.jsx)("span",{children:"Optional"}),(0,n.jsx)("textarea",{id:"setup-use",rows:2,value:L.useCase,onChange:e=>I("useCase",e.target.value),maxLength:500,placeholder:"e.g. Payment retries before every release",disabled:!t||P})]}),(0,n.jsx)("p",{className:"setup-help",children:"These details describe your team. This setup does not invite teammates or enforce SSO."}),(0,n.jsxs)("details",{className:"setup-appearance",children:[(0,n.jsx)("summary",{children:"Appearance and accessibility"}),(0,n.jsxs)("fieldset",{className:"setup-choice",children:[(0,n.jsx)("legend",{children:"Layout"}),(0,n.jsx)("div",{className:"setup-segmented",children:[{label:"Comfortable",value:!1},{label:"Compact",value:!0}].map(e=>(0,n.jsxs)("label",{children:[(0,n.jsx)("input",{type:"radio",name:"setup-density",checked:k.compact===e.value,onChange:()=>C(t=>({...t,compact:e.value}))}),(0,n.jsx)("span",{children:e.label})]},e.label))})]}),(0,n.jsxs)("fieldset",{className:"setup-choice",children:[(0,n.jsx)("legend",{children:"Background"}),(0,n.jsx)("div",{className:"setup-scenes",children:["auto","morning","afternoon","evening"].map(e=>(0,n.jsxs)("label",{children:[(0,n.jsx)("input",{type:"radio",name:"setup-artwork",checked:k.artwork===e,onChange:()=>C(t=>({...t,artwork:e}))}),(0,n.jsx)("span",{className:"setup-scene-swatch".concat("auto"===e?" automatic":""),style:"auto"!==e?{backgroundImage:"url('assets/dashboard/".concat(d[e],"')")}:void 0,children:"auto"===e&&(0,n.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none","aria-hidden":"true",children:[(0,n.jsx)("circle",{cx:"12",cy:"12",r:"7",stroke:"currentColor",strokeWidth:"1.5"}),(0,n.jsx)("path",{d:"M12 8v4l3 2",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]})}),(0,n.jsx)("span",{children:"auto"===e?"Automatic":e[0].toUpperCase()+e.slice(1)})]},e))}),(0,n.jsx)("p",{className:"setup-help",children:"auto"===k.artwork?"Changes with your local time.":"Keep this scene throughout the day."})]}),(0,n.jsxs)("div",{className:"setup-toggle-list",children:[(0,n.jsxs)("label",{children:[(0,n.jsxs)("span",{children:[(0,n.jsx)("strong",{children:"Live updates"}),(0,n.jsx)("small",{children:"Keep projects and test results up to date."})]}),(0,n.jsx)("input",{type:"checkbox",role:"switch",checked:k.autoRefresh,onChange:e=>C(t=>({...t,autoRefresh:e.target.checked}))})]}),(0,n.jsxs)("label",{children:[(0,n.jsxs)("span",{children:[(0,n.jsx)("strong",{children:"Reduce motion"}),(0,n.jsx)("small",{children:"Use fewer animations and transitions."})]}),(0,n.jsx)("input",{type:"checkbox",role:"switch",checked:k.reduceMotion,onChange:e=>C(t=>({...t,reduceMotion:e.target.checked}))})]})]})]}),(0,n.jsxs)("button",{type:"submit",className:"setup-primary",disabled:!t||P,children:[P?"Saving…":"Save workspace"," ",(0,n.jsx)(h,{})]})]}),2===s&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("p",{className:"setup-connect-intro",children:"Start in your repository’s terminal."}),(0,n.jsxs)("div",{className:"setup-terminal",children:[(0,n.jsxs)("div",{className:"setup-command-label",children:[(0,n.jsx)("span",{children:"01"}),(0,n.jsx)("strong",{children:"Connect your terminal"}),J&&(0,n.jsxs)("span",{className:"setup-connected",children:[(0,n.jsx)(m,{}),"Connected"]})]}),(r="npx agenttwin init",(0,n.jsxs)("div",{className:"setup-command",children:[(0,n.jsx)("code",{children:r}),(0,n.jsx)("button",{type:"button",onClick:()=>ep(r),"aria-label":"Copy ".concat(r),children:ee===r?(0,n.jsx)(m,{}):(0,n.jsxs)("svg",{viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:[(0,n.jsx)("rect",{x:"7",y:"7",width:"9",height:"10",rx:"2",stroke:"currentColor",strokeWidth:"1.4"}),(0,n.jsx)("path",{d:"M12 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2",stroke:"currentColor",strokeWidth:"1.4"})]})})]})),(0,n.jsx)("p",{className:"setup-help",children:"Run this inside your application repository. AgentTwin detects the project and its services, then guides you through connecting and sharing. Approve the terminal connection in this browser once. Init then syncs your project automatically; future runs use the saved connection."}),!J&&(0,n.jsxs)("details",{className:"setup-pairing",open:U||!!(null==t||null==(a=t.workspaceProfile)?void 0:a.completedAt),children:[(0,n.jsx)("summary",{children:U?"Confirm your terminal connection":"I have a terminal code"}),(0,n.jsxs)("form",{onSubmit:ed,children:[(0,n.jsxs)("label",{htmlFor:"setup-terminal-code",children:["Connection code",(0,n.jsx)("input",{id:"setup-terminal-code",name:"userCode",value:W,onChange:e=>z(e.target.value.toUpperCase()),autoComplete:"off",autoCapitalize:"characters",spellCheck:!1,placeholder:"10-character code",minLength:10,maxLength:10,pattern:"[A-Fa-f0-9]{10}",required:!0,disabled:!t||M})]}),(0,n.jsx)("button",{type:"submit",className:"setup-secondary",disabled:!t||M,children:M?"Connecting…":"Connect terminal"})]}),(0,n.jsx)("p",{className:"setup-help",children:"Compare this code with your terminal before approving. Connecting lets it sync project discovery and test evidence to your workspace. Application source and credentials stay local."})]}),B&&(0,n.jsx)("p",{className:"setup-feedback",role:"status",children:B})]}),(0,n.jsx)("p",{className:"setup-help",role:"status",children:G.length?"Project connected.":J?"Terminal connected. Waiting for init to finish syncing your project…":"Enter the code from your terminal to connect this project."}),(0,n.jsxs)("button",{type:"button",className:"setup-secondary setup-check",onClick:eu,disabled:!t||H,children:[H?"Checking…":G.length?"Check again":"Check for my project",!H&&(0,n.jsx)(h,{})]}),V&&(0,n.jsx)("p",{className:"setup-feedback",role:"status",children:V}),G.map(e=>(0,n.jsxs)("div",{className:"setup-project",children:[(0,n.jsx)(m,{}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:e.name}),(0,n.jsxs)("span",{children:[e.tools," resource",1===e.tools?"":"s"," \xb7 ",e.workflows," workflow candidate",1===e.workflows?"":"s"]})]})]},e.name)),(0,n.jsxs)("div",{className:"setup-finish",children:[(0,n.jsxs)("button",{type:"button",className:"setup-primary",onClick:ec,disabled:!t||H||M||P,children:[P?"Saving…":G.length?"Open my workspace":"Connect later"," ",(0,n.jsx)(h,{})]}),!G.length&&(0,n.jsx)("p",{children:"Connect a project later from your workspace."}),es&&(0,n.jsx)("a",{href:"/dashboard/#home",children:"Open workspace without saving"})]})]})]})]},e)})}),(0,n.jsx)("p",{className:"setup-notice",role:"status","aria-live":"polite",children:N})]}),(0,n.jsxs)("aside",{className:"setup-preview".concat(k.compact?" compact":""),"aria-label":"Live workspace preview",children:[(0,n.jsxs)("div",{className:"setup-preview-heading",children:[(0,n.jsx)("span",{children:"Workspace preview"}),(0,n.jsx)("span",{className:"setup-preview-scene",children:er[0].toUpperCase()+er.slice(1)})]}),(0,n.jsxs)("div",{className:"setup-preview-window dashboard-preview",children:[(0,n.jsxs)("div",{className:"setup-preview-nav",children:[(0,n.jsx)("img",{src:"assets/logo/mark-twin-rings.svg",width:"18",height:"18",alt:""}),(0,n.jsx)("strong",{children:"AgentTwin"}),(0,n.jsx)("span",{className:"setup-preview-avatar",children:A?A[0].toUpperCase():"A"})]}),(0,n.jsx)("div",{className:"preview-navigation","aria-label":"Dashboard navigation preview",children:["Home","Environment","Workflows","Runs","Settings"].map(e=>(0,n.jsx)("span",{className:"Home"===e?"selected":void 0,children:e},e))}),(0,n.jsxs)("div",{className:"setup-preview-hero",children:[(0,n.jsx)("h3",{children:"What should your agent test?"}),(0,n.jsxs)("div",{className:"setup-preview-composer",children:[(0,n.jsx)("span",{children:"Ask about a workflow or test result"}),(0,n.jsx)("span",{"aria-hidden":"true",children:"↑"}),(0,n.jsx)("span",{className:"preview-microphone","aria-hidden":"true",children:(0,n.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.6",children:[(0,n.jsx)("rect",{x:"9",y:"3",width:"6",height:"12",rx:"3"}),(0,n.jsx)("path",{d:"M5 10v2a7 7 0 0 0 14 0v-2M12 19v3"})]})})]})]}),(0,n.jsxs)("div",{className:"preview-dashboard-body",children:[(0,n.jsxs)("div",{className:"preview-connect-banner",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:(null==(e=G[0])?void 0:e.name)||"Connect your project"}),(0,n.jsx)("p",{children:G[0]?"".concat(G[0].tools," resources \xb7 ").concat(G[0].workflows," workflow candidates"):"Start in your repository with npx agenttwin init."})]}),(0,n.jsxs)("span",{className:"preview-action",children:[G.length?"View project":"Connect project"," ",(0,n.jsx)(h,{})]})]}),(0,n.jsxs)("div",{className:"preview-workspace-heading",children:[(0,n.jsx)("span",{children:O||"Your workspace"}),(0,n.jsx)("span",{children:"⊞ Customize"})]}),(0,n.jsxs)("div",{className:"preview-widget-grid",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Project discovery"}),(0,n.jsx)("p",{children:G[0]?"".concat(G[0].name,": ").concat(G[0].tools," detected resources."):"Connect and sync your project to see its resources and workflow candidates."})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Test results"}),(0,n.jsx)("p",{children:"Run receipts, assertions and recorded state changes appear here after a test."})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Git activity"}),(0,n.jsx)("p",{children:"Repository commits and workflow changes."}),(0,n.jsx)("code",{children:"npx agenttwin init"})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Observed activities"}),(0,n.jsx)("p",{children:"Reads, writes, retries and injected failures recorded during a run."})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Working now"}),(0,n.jsx)("p",{children:"Follow the progress of running workflow tests."})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Needs attention"}),(0,n.jsx)("p",{children:"Inspect failed checks and the evidence behind them."})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Last execution"}),(0,n.jsx)("p",{children:"The tested revision, runtime and outcome of your latest run."})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("strong",{children:"Test readiness"}),(0,n.jsx)("p",{children:"Review dependencies, inputs and required outcomes."})]})]})]})]}),(0,n.jsx)("p",{className:"setup-preview-caption",children:2===y?G.length?"Project found. You can start reviewing workflows.":X?"Your project appears here after its first sync.":"Connect your own project when you’re ready.":"Your application, its test world and the evidence from each run."})]})]}),(0,n.jsxs)("footer",{className:"onboarding-footer",children:[(0,n.jsxs)("span",{children:[y+1," of 3"]}),(0,n.jsx)("span",{children:"Profile and workspace save to your account."})]})]})]})}},9022:()=>{}},e=>{e.O(0,[3935,4295,9681,6787,8441,1255,7358],()=>e(e.s=2039)),_N_E=e.O()}]);
|