diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..99799f6 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Repository-wide stewardship. Required review remains a branch rule rather than +# a CODEOWNERS-only rule so knowledgeable contributors can review one another. +* @BenAlaa diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..ebed74e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,63 @@ +name: Book engine bug +description: Report a reproducible problem in navigation, rendering, interaction, search, accessibility, or build behavior. +title: "fix(engine): " +labels: [bug] +body: + - type: markdown + attributes: + value: Use the source-correction form for an inaccurate architectural claim and the upstream tracker for a T3 Code product bug. + - type: input + id: page + attributes: + label: Page or route + placeholder: /runtime-topologies/ + validations: + required: true + - type: textarea + id: observed + attributes: + label: Observed behavior + description: Explain what happened and include the exact error when available. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Reproduction + description: Give the shortest reliable sequence, including diagram controls or keyboard input when relevant. + placeholder: | + 1. Open … + 2. Select … + 3. Observe … + validations: + required: true + - type: input + id: environment + attributes: + label: Environment + description: Browser and version, operating system, input method, and deployed or local build. + placeholder: Firefox 145, macOS, trackpad, GitHub Pages + validations: + required: true + - type: textarea + id: accessibility + attributes: + label: Accessibility or reduced-motion impact + description: Note keyboard, screen-reader, focus, contrast, motion, zoom, or print impact if relevant. + validations: + required: false + - type: checkboxes + id: checks + attributes: + label: Report checks + options: + - label: This is a T3 Code Decoded book/engine issue, not an upstream T3 Code product issue. + required: true + - label: I checked for an existing report. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3a2b430 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Upstream T3 Code support + url: https://github.com/pingdotgg/t3code/issues + about: Report T3 Code product bugs to the upstream project, not this study guide. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..3d76f22 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,42 @@ +name: Book or engine proposal +description: Propose a chapter, visualization, simulator, accessibility, or engine improvement. +title: "feat(book): " +labels: [proposal] +body: + - type: textarea + id: problem + attributes: + label: Reader problem + description: What is currently difficult to understand or use? + validations: + required: true + - type: textarea + id: outcome + attributes: + label: Proposed outcome + description: Describe the chapter, figure, lab, or engine behavior—not only an implementation. + validations: + required: true + - type: textarea + id: sources + attributes: + label: Likely source anchors + description: List relevant T3 Code paths or this repository's engine files. + validations: + required: false + - type: textarea + id: alternatives + attributes: + label: Alternatives and scope + description: What smaller explanation or existing component could solve it? + validations: + required: false + - type: checkboxes + id: checklist + attributes: + label: Proposal checks + options: + - label: I checked BOOK_PLAN.md for an existing chapter or planned artifact. + required: true + - label: This is about the study guide, not an upstream T3 Code product bug. + required: true diff --git a/.github/ISSUE_TEMPLATE/source-correction.yml b/.github/ISSUE_TEMPLATE/source-correction.yml new file mode 100644 index 0000000..60381b7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/source-correction.yml @@ -0,0 +1,49 @@ +name: Source correction +description: Report a factual, source-link, or evidence-class problem in the book. +title: "fix(book): " +labels: [source-correction] +body: + - type: markdown + attributes: + value: Thank you for helping keep the book grounded. Please cite the pinned source when possible. + - type: input + id: chapter + attributes: + label: Chapter or page + placeholder: Chapter 10 · Events, receipts, and idempotency + validations: + required: true + - type: textarea + id: current + attributes: + label: Current claim + description: Quote or summarize the claim that needs correction. + validations: + required: true + - type: textarea + id: evidence + attributes: + label: Source evidence + description: Add repository paths, line ranges, tests, or immutable links. + placeholder: apps/server/src/...:120-150 + validations: + required: true + - type: dropdown + id: classification + attributes: + label: Suspected problem + options: + - Incorrect verified behavior + - Documented intent presented as behavior + - Inference not labeled + - Future or latent capability presented as shipped + - Stale or broken source reference + - Other evidence problem + validations: + required: true + - type: textarea + id: correction + attributes: + label: Suggested correction + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..2ff1e7d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,36 @@ +## Outcome + + + +## Scope + + + +### Non-goals + + + +## Evidence + +- Canonical source lock: `sources/t3code.lock.json` (read and verified by CI) +- Primary anchors: + - +- Claim class notes: +- Discrepancies or uncertainty: + +## Visuals and interaction + + + +## Validation + +- [ ] `npm test` +- [ ] `npm run build` +- [ ] `npm run source:check` when source excerpts changed +- [ ] Internal routes, source links, and headings checked +- [ ] Claims reviewed at the pinned revision +- [ ] Accessibility and static print state checked for changed visuals + +## Review focus + + diff --git a/.github/REPOSITORY_SETUP.md b/.github/REPOSITORY_SETUP.md new file mode 100644 index 0000000..4014cd0 --- /dev/null +++ b/.github/REPOSITORY_SETUP.md @@ -0,0 +1,151 @@ +# Public repository launch runbook + +This is the owner checklist for publishing T3 Code Decoded. It deliberately keeps +repository creation, policy activation, branch publication, and Pages deployment +as separate checkpoints. Completing one checkpoint does not authorize the next. + +## Fixed decisions + +- Owner: personal GitHub account [`BenAlaa`](https://github.com/BenAlaa), never the + EasyGenerator organization. +- Visibility: public. +- Repository and Pages project name: `t3code-decoded`. +- Default branch: `main`; do not create or retain `master`. +- Authored changes: pull requests only. Never push project commits directly to + `main`. +- Merge method: rebase merge, preserving the fine-grained Conventional Commits. +- Solo-owner escape hatch: `BenAlaa` may bypass rules **for pull requests only**. + The bypass may merge an existing owner PR; it must not become a direct-push path. +- Pages source: a GitHub Actions artifact, never a committed `dist/` branch. + +## 1. Local preflight + +- [ ] `git status` contains only the intended milestone. +- [ ] `npm ci` succeeds from the lockfile. +- [ ] `npm run source:check` succeeds against the locked T3 Code checkout. +- [ ] `npm test` succeeds. +- [ ] `npm run build` succeeds with `/`. +- [ ] `BASE_PATH=/t3code-decoded/ SITE_URL=https://benalaa.github.io npm run build` + succeeds. +- [ ] Every local commit that will be replayed follows Conventional Commits. +- [ ] The GitHub CLI or browser session is visibly authenticated as `BenAlaa`. + +## 2. Create the inert public remote + +Create `BenAlaa/t3code-decoded` as public with GitHub's generated README. That one +placeholder commit establishes remote `main`; do not initialize another license or +`.gitignore`, and do not push the local repository during creation. + +- [ ] Confirm the owner is exactly `BenAlaa` and visibility is **Public**. +- [ ] Confirm the default branch is `main` and no `master` branch exists. +- [ ] Add the description, Pages URL, and topics such as `t3code`, `architecture`, + `astro`, `effect`, `reverse-engineering`, and `interactive-book`. +- [ ] Add the remote locally and fetch the placeholder branch read-only. + +## 3. Protect `main` before publishing authored work + +In **Settings → Rules → Rulesets**, create an active branch ruleset named +`protected-main` targeting the default branch. + +Bypass list: + +- [ ] Add the `BenAlaa` user actor. +- [ ] Change its bypass mode from **Always allow** to **For pull requests only**. +- [ ] Do not grant the bypass to write/maintain roles or automation generally. + +Rules: + +- [ ] Restrict deletions. +- [ ] Require a pull request before merging. +- [ ] Require one approving review. +- [ ] Dismiss stale approvals when new commits are pushed. +- [ ] Require review from Code Owners. +- [ ] Require approval of the most recent reviewable push. +- [ ] Require all review conversations to be resolved. +- [ ] Require linear history. +- [ ] Block force pushes. + +Repository merge settings: + +- [ ] Enable **rebase merging**. +- [ ] Disable merge commits and squash merging so reviewed fine-grained commits + survive on `main`. +- [ ] Automatically delete head branches after merge. + +The first publication PR introduces the workflows, so the status-check contexts do +not exist when the initial ruleset is created. Open that PR, wait for both checks to +run, then edit the ruleset before merging: + +- [ ] Require `Validate and build`. +- [ ] Require `Conventional changes`. +- [ ] Require branches to be up to date before merging. +- [ ] Verify the ruleset is **Active**, then inspect Rule Insights after the first + owner bypass. + +## 4. Replay the local milestones through PR branches + +The local history and GitHub placeholder have unrelated roots. Do not merge those +roots and do not force the local branch onto remote `main`. For each publication +milestone, create a clean branch from the latest `origin/main`, then cherry-pick +the already-reviewed local commits in their original order. + +Recommended PR sequence: + +1. `bootstrap/initial-edition` — book engine, source pipeline, front matter, + Chapters 1–4, and the public governance/CI foundation. The opening maps link + into Part I, so this is the smallest complete milestone that passes the + built-site link gate; +2. `docs/part-02-boot-connect` — Chapters 5–8 and their evidence; +3. one branch and PR per later coherent part or review milestone. + +For every branch: + +- [ ] Branch from the latest protected remote `main`. +- [ ] Replay only the intended fine-grained commits; resolve no unrelated changes. +- [ ] Run the full local preflight again. +- [ ] Push the named feature/docs/chore branch, never `main`. +- [ ] Use a Conventional Commit title for the PR and complete every template + section with outcome, scope, evidence, validation, and review focus. +- [ ] Review the Files changed and commit list as `BenAlaa`. +- [ ] Resolve conversations and wait for required checks. +- [ ] For owner-authored PRs, choose the explicit ruleset bypass in the merge box; + do not disable or edit protection merely to self-merge. +- [ ] Rebase-merge, verify `main`, and delete the remote head branch. + +## 5. Configure GitHub Pages + +After the CI foundation reaches `main`: + +- [ ] In **Settings → Pages**, select **GitHub Actions** as the source. +- [ ] Keep the `github-pages` environment restricted to deployments from `main`. +- [ ] Confirm the Pages workflow build job has only `contents: read` and the deploy + job alone has `pages: write` plus `id-token: write`. +- [ ] Confirm every external action is pinned to an immutable full commit SHA. +- [ ] Confirm Pages checks out the T3 revision read from + `sources/t3code.lock.json` and runs `npm run source:check` before upload. +- [ ] Verify canonical URLs, assets, search, favicon, internal links, diagrams, and + expanded zoom/pan at `https://benalaa.github.io/t3code-decoded/`. + +## 6. Community and security settings + +- [ ] Enable Issues and preserve the bug, source-correction, and proposal forms. +- [ ] Create labels `bug`, `proposal`, `source-correction`, `accessibility`, + `documentation`, `engine`, and `dependencies`. +- [ ] Enable the dependency graph, Dependabot alerts, and Dependabot security + updates. +- [ ] Enable private vulnerability reporting so the link in `SECURITY.md` works. +- [ ] Confirm `CODEOWNERS` resolves `@BenAlaa` and the PR template loads. +- [ ] Confirm the repository displays the mixed-license notice and upstream T3 + Code attribution. + +## 7. Launch evidence + +Record the final URLs or screenshots in the launch PR: + +- [ ] public repository; +- [ ] active `protected-main` ruleset and pull-request-only bypass; +- [ ] required checks on a real PR; +- [ ] successful Pages deployment; +- [ ] live book route and search result; +- [ ] private vulnerability reporting enabled; +- [ ] no `master`, no published `dist/`, and no authored direct commit to `main`. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..cfc2756 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,27 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: / + schedule: + interval: weekly + day: monday + groups: + astro-book-engine: + patterns: + - astro + - "@astrojs/*" + search-and-diagrams: + patterns: + - pagefind + - mermaid + commit-message: + prefix: chore + include: scope + + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + commit-message: + prefix: chore + include: scope diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..fa700a4 --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,91 @@ +name: Book quality + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: quality-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + metadata: + name: Conventional changes + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + + steps: + - name: Check out pull request history + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Validate title, body, and every commit subject + run: node scripts/validate-change-metadata.mjs + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + + book: + name: Validate and build + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + + steps: + - name: Check out the book + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Read the canonical source lock + id: source-lock + run: node scripts/export-source-lock.mjs >> "$GITHUB_OUTPUT" + + - name: Fetch the pinned T3 Code source + env: + T3CODE_COMMIT: ${{ steps.source-lock.outputs.commit }} + run: | + git init .source/t3code + git -C .source/t3code remote add origin https://github.com/pingdotgg/t3code.git + git -C .source/t3code fetch --depth=1 --no-tags origin "$T3CODE_COMMIT" + git -C .source/t3code checkout --detach "$T3CODE_COMMIT" + test "$(git -C .source/t3code rev-parse HEAD)" = "$T3CODE_COMMIT" + + - name: Set up Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24.13.1 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Verify generated excerpts against the source lock + run: npm run source:check + env: + T3CODE_SOURCE_DIR: ${{ github.workspace }}/.source/t3code + + - name: Run tests + run: npm test + + - name: Build the root-hosted shape + run: npm run build + env: + SITE_URL: https://benalaa.github.io + + - name: Build the GitHub Pages shape + run: npm run build + env: + BASE_PATH: /t3code-decoded/ + SITE_URL: https://benalaa.github.io diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5414b69 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules/ +dist/ +.astro/ +.DS_Store +*.log + +# Local source checkout pointers and authoring caches. +.source/ +.source-cache/ +.env +.env.local diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..fa79833 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,38 @@ +# Community code of conduct + +T3 Code Decoded is a technical learning project. Participation should make it +safer and easier for people with different backgrounds to inspect evidence, ask +questions, and change their minds. + +## Expected behavior + +- Be respectful, specific, and patient. +- Critique claims and evidence rather than people. +- Distinguish facts, interpretations, preferences, and uncertainty. +- Welcome corrections and credit the people who surface them. +- Respect privacy, source licenses, and upstream maintainers' time. +- Keep product support requests in the upstream project's channels. + +## Unacceptable behavior + +- Harassment, discrimination, threats, sexualized attention, or personal attacks. +- Publishing another person's private information or credentials. +- Deliberately misleading source attribution or fabricated evidence. +- Sustained disruption, spam, or bad-faith demands. + +## Enforcement + +Repository maintainers may edit or remove contributions and may temporarily or +permanently restrict participation when behavior harms the community. Report +conduct concerns privately to Ahmed Alaa through the contact methods on +[`@BenAlaa`'s GitHub profile](https://github.com/BenAlaa). Do not open a public +issue containing sensitive details. + +Maintainers will consider context, protect reporter privacy as far as practical, +and communicate consequences proportionately. Good-faith disagreement about an +architectural interpretation is not misconduct. + +## Scope + +This policy applies in repository spaces and when someone is publicly representing +the project. Upstream T3 Code spaces have their own governance. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ccf6a27 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +T3 Code Decoded — software license and content notice + +This is a mixed-license repository. The MIT License below applies to the site +engine, components, styles, scripts, tests, workflows, and other original software. +Original book prose and diagrams are licensed separately under CC BY 4.0 as +described in LICENSE-CONTENT. Third-party excerpts, marks, and the supplied cover +artwork are excluded from both grants; see NOTICE.md. + +MIT License + +Copyright (c) 2026 Ahmed Alaa and T3 Code Decoded contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the software portions of this repository and associated software documentation +files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE-CODE b/LICENSE-CODE new file mode 100644 index 0000000..e0d91c5 --- /dev/null +++ b/LICENSE-CODE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ahmed Alaa and T3 Code Decoded contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE-CONTENT b/LICENSE-CONTENT new file mode 100644 index 0000000..d60dea1 --- /dev/null +++ b/LICENSE-CONTENT @@ -0,0 +1,22 @@ +Creative Commons Attribution 4.0 International — license notice and summary + +Copyright (c) 2026 Ahmed Alaa and T3 Code Decoded contributors + +Original book prose and original diagrams in this repository are licensed under +the Creative Commons Attribution 4.0 International License (CC BY 4.0). + +You are free to share and adapt that material for any purpose, including +commercially, provided that you give appropriate credit, provide a link to the +license, and indicate if changes were made. You may not apply legal terms or +technological measures that legally restrict others from doing anything the +license permits. + +This file summarizes the grant for repository navigation; it is not a substitute +for the license. The complete CC BY 4.0 legal code governs and is available at: +https://creativecommons.org/licenses/by/4.0/legalcode + +Suggested attribution: “T3 Code Decoded” by Ahmed Alaa and contributors, +https://github.com/BenAlaa/t3code-decoded, licensed under CC BY 4.0. + +This license does not cover third-party source excerpts, trademarks, logos, or the +supplied cover artwork. See NOTICE.md for attribution and scope. diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..5fdcba0 --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,58 @@ +# Notices and attribution + +## T3 Code + +This repository contains short excerpts from T3 Code solely to explain its +architecture. The upstream project is available at: + +https://github.com/pingdotgg/t3code + +The source snapshot used by this edition is commit +`fa219001dc2f14cfd9c7774c2c03c153359144be`. T3 Code is licensed under the MIT +License. The following upstream notice and permission terms remain applicable to +every included excerpt: + +> MIT License +> +> Copyright (c) 2026 T3 Tools Inc. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + +The excerpt manifest, generated checksums, and immutable source links make the +boundary between upstream code and original commentary inspectable. + +## Original material + +The site engine, scripts, and original software in this repository are available +under `LICENSE-CODE`. Original prose and diagrams by Ahmed Alaa and project +contributors are available under `LICENSE-CONTENT`, unless a file states +otherwise. The root `LICENSE` routes these scopes. + +## Cover + +The project owner supplied `cover.png` and authorized its inclusion in this public +repository and published book. It is a project asset excluded from both the MIT +and CC BY 4.0 grants. Its inclusion does not grant reuse rights or broader rights +to third-party names, logos, or marks depicted in the artwork. + +## Independence + +T3 Code Decoded is an independent, unofficial study guide. It is not maintained, +sponsored, or endorsed by Ping Labs, T3 Code, or the vendors of the provider +harnesses it documents. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..3897970 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,45 @@ +# Security policy + +## Supported version + +The current `main` branch and deployed GitHub Pages edition are supported. Older +source-lock editions are historical snapshots and do not receive security fixes. + +## Reporting a vulnerability + +Use [GitHub's private vulnerability reporting +form](https://github.com/BenAlaa/t3code-decoded/security/advisories/new) for this +repository. If the form is unavailable, contact Ahmed Alaa privately through the +contact information on [`@BenAlaa`'s GitHub profile](https://github.com/BenAlaa). + +Please include: + +- the affected page, component, workflow, or dependency; +- reproduction steps and realistic impact; +- whether the issue affects local development, contributors, or public readers; +- any suggested mitigation; +- whether and when disclosure has occurred elsewhere. + +Do not open a public issue for a vulnerability before the maintainer has had a +reasonable chance to investigate. + +## Scope + +In scope: + +- script injection or unsafe rendering in book content, diagrams, or search; +- dependency or GitHub Actions compromise affecting contributors or deployment; +- source-extraction path traversal or unsafe file handling; +- accidental publication of credentials or private material; +- a deployed-site configuration that creates a meaningful security risk. + +Out of scope: + +- vulnerabilities in T3 Code itself—report those to `pingdotgg/t3code`; +- missing security headers that have no practical impact on this static site; +- automated scanner output without a reproducible attack; +- social engineering, denial of service, or attacks on GitHub infrastructure. + +The book is an independent architecture study and is not a security advisory for +the upstream project. Findings about upstream code are presented as source-grounded +design analysis, not exploit claims. diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..e9d1e50 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,27 @@ +import { defineConfig } from "astro/config"; +import mdx from "@astrojs/mdx"; + +const base = process.env.BASE_PATH || "/"; +if (process.env.CI && !process.env.SITE_URL) { + throw new Error("SITE_URL is required for CI builds so canonical and social URLs cannot silently disappear."); +} + +export default defineConfig({ + output: "static", + site: process.env.SITE_URL, + base, + trailingSlash: "always", + build: { + format: "directory", + }, + integrations: [mdx()], + markdown: { + shikiConfig: { + themes: { + light: "github-light", + dark: "github-dark", + }, + wrap: true, + }, + }, +}); diff --git a/cover.png b/cover.png new file mode 100644 index 0000000..ab4796f Binary files /dev/null and b/cover.png differ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0dee959 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7411 @@ +{ + "name": "t3code-decoded", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "t3code-decoded", + "version": "0.1.0", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@astrojs/mdx": "7.0.7", + "astro": "7.2.4", + "mermaid": "11.17.0" + }, + "devDependencies": { + "pagefind": "1.5.2", + "typescript": "6.0.3" + }, + "engines": { + "node": ">=24.10.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@astrojs/compiler-binding": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.3.2.tgz", + "integrity": "sha512-8w/9CWmYrAJJ8N0SY3O43ws2BgxoW6u3QsD8u2mE140lMYAlwh+tlNoUeSBq22wVheFuiBbR212l6ixZ2IIgCQ==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@astrojs/compiler-binding-darwin-arm64": "0.3.2", + "@astrojs/compiler-binding-darwin-x64": "0.3.2", + "@astrojs/compiler-binding-linux-arm64-gnu": "0.3.2", + "@astrojs/compiler-binding-linux-arm64-musl": "0.3.2", + "@astrojs/compiler-binding-linux-x64-gnu": "0.3.2", + "@astrojs/compiler-binding-linux-x64-musl": "0.3.2", + "@astrojs/compiler-binding-wasm32-wasi": "0.3.2", + "@astrojs/compiler-binding-win32-arm64-msvc": "0.3.2", + "@astrojs/compiler-binding-win32-x64-msvc": "0.3.2" + } + }, + "node_modules/@astrojs/compiler-binding-darwin-arm64": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.3.2.tgz", + "integrity": "sha512-MM8tn8CSimcfytaOla4b6acN8mKWiL/rlAA1fpT3/Wl7dNGSE4y8FjTN/zJVNnb63CsLWG5zZwCt01TXtDKh9g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-darwin-x64": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.3.2.tgz", + "integrity": "sha512-2lXOlzf8xb7jLomRsf/aswh61/NnGusynB2OwFkK6k4pmOtpfXMYnG0PLfXrEvxXYj69NdCnmUYXtHDd+JOOag==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-arm64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.3.2.tgz", + "integrity": "sha512-BmU3kWj7qnLrd4vzm49zFEPJ5oFnn1tCT4Vt9hZbqdU5Cmb8GZl7fn6VFsnNfe7B18a2gIFtVzbLINtYl5kBjQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-arm64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.3.2.tgz", + "integrity": "sha512-f0heT9ZZEseSu5bHCeb80eL2DH07ArE6U9xi1WT/PEusNjzPmEr3GJsjG1tRLo5VYUUYX7h3ScaqGmGrMOVGmw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-x64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.3.2.tgz", + "integrity": "sha512-M8fOUt0itRpqiGyoEA/ij184s8O+hqbCz3+YozRusOOM3osgGljpDThhbKAJjqh82wOo6FioQ4w8PBvU1XMD5Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-x64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.3.2.tgz", + "integrity": "sha512-/Kebk8sO6HnLeSd691JkaAPfN7CqR9/KEXmWvyNPkaKNGmj8rTZ/lf2uXtnPu92Lan84UrKdIKVPy1fSo2encQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-wasm32-wasi": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.3.2.tgz", + "integrity": "sha512-pUA6xbcOSB7DhfzIArB8BCAkFfAIqriiR7zl5zOStd6oU2G0kIKj+GUdGnyXyhfiv881Hffyk5tC0mR18sDjDw==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.3.2.tgz", + "integrity": "sha512-ESruf+6Qkl1trHUFxI6GSf6t52j8yN2kCNSzMWdzt7V/T09tFHrYzrVaJQohb2C9bJUH76pNvX6Zb51+xCQc9Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-x64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.3.2.tgz", + "integrity": "sha512-wzzVrEbOwbsLWOdEbocskjMRx2aZPxJ7ZbmL+jnpBamFwmigm+2M/wzuM6JWncocgYwLic1csSpalBh96kQKXA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-rs": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.3.2.tgz", + "integrity": "sha512-xlx/T7JovIKduu4ucbTQUxQ5+Q8wxkHxhLjnZk3VlJbhbQ9RLvvuDk1p2YYFYFQ5y14dVm3FGGO4isQXa4F+Tg==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler-binding": "0.3.2" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.4.tgz", + "integrity": "sha512-nozZSy/mKYLqe4YrqbKtdOszedAfXYCtw3wZ0d+CAjz4GqQ4L9rl1ltIL5BlgwmYVinJg/RZ0MgGuWOdlyRZlA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "js-yaml": "^4.3.0", + "picomatch": "^4.0.4", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "unified": "^11.0.5" + } + }, + "node_modules/@astrojs/markdown-remark": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.4.tgz", + "integrity": "sha512-MvspGMynWKAjTe4/lTUdmBPHIFKNVLTCF6UlyWGogTGzNrTvjD+D4n48k7h8swxsEPKHK2TwxkZO7uoaCv1Pow==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.4", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.1.0", + "unist-util-visit-parents": "^6.0.2", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/markdown-satteri": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.7.tgz", + "integrity": "sha512-NHcHbrKW/opbZnTZQ5nH293BdcK2VV0tjuzI88CLnvy2njiEJVwUQ5KFnYd4NoWgHJCY/I1CyjGWCR4Vv3khXQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.4", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "satteri": "^0.10.3" + } + }, + "node_modules/@astrojs/mdx": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-7.0.7.tgz", + "integrity": "sha512-hv+NJh2s+/KDrjXaYNOaS344e3M2ekMXHBR7x9EwBwE3VvE1y/9Ifh1rhR1H2zK2sMgXoUnakI9e9ZeCKPX9/Q==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.4", + "@astrojs/markdown-remark": "7.2.4", + "@mdx-js/mdx": "^3.1.1", + "acorn": "^8.16.0", + "es-module-lexer": "^2.0.0", + "estree-util-visit": "^2.0.0", + "hast-util-to-html": "^9.0.5", + "piccolore": "^0.1.3", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.6", + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "@astrojs/markdown-satteri": "^0.3.1", + "astro": "^7.0.0" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-satteri": { + "optional": true + } + } + }, + "node_modules/@astrojs/prism": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", + "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", + "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.4.0", + "dset": "^3.1.4", + "is-docker": "^4.0.0", + "package-manager-detector": "^1.6.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", + "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", + "license": "MIT" + }, + "node_modules/@bruits/satteri-darwin-arm64": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.10.5.tgz", + "integrity": "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@bruits/satteri-darwin-x64": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.10.5.tgz", + "integrity": "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-gnu": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.10.5.tgz", + "integrity": "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-musl": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.10.5.tgz", + "integrity": "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-gnu": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.10.5.tgz", + "integrity": "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-musl": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.10.5.tgz", + "integrity": "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-wasm32-wasi": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.10.5.tgz", + "integrity": "sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.2.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-win32-arm64-msvc": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.10.5.tgz", + "integrity": "sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@bruits/satteri-win32-x64-msvc": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.10.5.tgz", + "integrity": "sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@capsizecss/unpack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz", + "integrity": "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@chevrotain/types": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz", + "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==", + "license": "Apache-2.0" + }, + "node_modules/@clack/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz", + "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", + "license": "MIT", + "dependencies": { + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" + } + }, + "node_modules/@clack/prompts": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz", + "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==", + "license": "MIT", + "dependencies": { + "@clack/core": "1.4.3", + "fast-string-width": "^3.0.2", + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.4.tgz", + "integrity": "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "import-meta-resolve": "^4.2.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mermaid-js/parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.2.1.tgz", + "integrity": "sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw==", + "license": "MIT", + "dependencies": { + "@chevrotain/types": "~11.1.2" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT" + }, + "node_modules/@oxc-project/types": { + "version": "0.146.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.146.0.tgz", + "integrity": "sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.5.2.tgz", + "integrity": "sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.5.2.tgz", + "integrity": "sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/freebsd-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.5.2.tgz", + "integrity": "sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.5.2.tgz", + "integrity": "sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.5.2.tgz", + "integrity": "sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/windows-arm64/-/windows-arm64-1.5.2.tgz", + "integrity": "sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.5.2.tgz", + "integrity": "sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.5.tgz", + "integrity": "sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.5.tgz", + "integrity": "sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.5.tgz", + "integrity": "sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.5.tgz", + "integrity": "sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.5.tgz", + "integrity": "sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.5.tgz", + "integrity": "sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.5.tgz", + "integrity": "sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.5.tgz", + "integrity": "sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.5.tgz", + "integrity": "sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.5.tgz", + "integrity": "sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.5.tgz", + "integrity": "sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.5.tgz", + "integrity": "sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.5.tgz", + "integrity": "sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.5.tgz", + "integrity": "sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.5.tgz", + "integrity": "sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "license": "MIT" + }, + "node_modules/@shikijs/core": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5", + "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-65Emv9fQiQQqphLlRkuQ5ypPsOmWPhtBGCMv61JDPEPMvsx+gzhGf74yw1a78xFKPj6zw4AgQICJoQv0vK9M2w==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.4.tgz", + "integrity": "sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", + "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "license": "ISC" + }, + "node_modules/@upsetjs/venn.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", + "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "license": "MIT", + "optionalDependencies": { + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/am-i-vibing": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.4.0.tgz", + "integrity": "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==", + "license": "MIT", + "dependencies": { + "process-ancestry": "^0.1.0" + }, + "bin": { + "am-i-vibing": "dist/cli.mjs" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/astro": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.2.4.tgz", + "integrity": "sha512-+cuLsBns2wwUHI9a10xZMbjrF91m7+QNwqTVeljTx0B8Lf+8h0LgVGjdVIL2FALDKD2I565lczeeS3BFC+KdZg==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler-rs": "^0.3.2", + "@astrojs/internal-helpers": "0.10.4", + "@astrojs/markdown-satteri": "0.3.7", + "@astrojs/telemetry": "3.3.3", + "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "am-i-vibing": "^0.4.0", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "ci-info": "^4.4.0", + "clsx": "^2.1.1", + "common-ancestor-path": "^2.0.0", + "cookie": "^2.0.1", + "devalue": "^5.8.1", + "diff": "^8.0.3", + "dset": "^3.1.4", + "es-module-lexer": "^2.0.0", + "esbuild": "^0.28.0", + "find-process": "^2.1.1", + "flattie": "^1.1.1", + "fontace": "~0.4.1", + "get-tsconfig": "5.0.0-beta.4", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "js-yaml": "^4.3.0", + "jsonc-parser": "^3.3.1", + "magic-string": "^1.0.0", + "magicast": "^0.5.2", + "mrmime": "^2.0.1", + "neotraverse": "^1.0.1", + "obug": "^2.1.1", + "p-limit": "^7.3.0", + "p-queue": "^9.1.0", + "package-manager-detector": "^1.6.0", + "piccolore": "^0.1.3", + "picomatch": "^4.0.4", + "semver": "^7.7.4", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "svgo": "^4.0.1", + "tinyclip": "^0.1.12", + "tinyexec": "^1.0.4", + "tinyglobby": "^0.2.15", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.5", + "unstorage": "^1.17.5", + "vite": "^8.0.13", + "vitefu": "^1.1.2", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^22.0.0", + "zod": "^4.3.6" + }, + "bin": { + "astro": "bin/astro.mjs" + }, + "engines": { + "node": ">=22.12.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/astrodotbuild" + }, + "optionalDependencies": { + "sharp": "^0.34.0 || ^0.35.0" + }, + "peerDependencies": { + "@astrojs/markdown-remark": "7.2.4" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-remark": { + "optional": true + } + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } + }, + "node_modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==", + "license": "MIT", + "engines": { + "node": ">=22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/cytoscape": { + "version": "3.34.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.34.1.tgz", + "integrity": "sha512-Lr0RvH9H75y9ar8h9Toy6u4lxRSCcxUq+hHcQ26sVWo6BnaQp1gwEZOYqwuYTZhyW7npyKnNLP8oJ2p1/3OZ7g==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz", + "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/dayjs": { + "version": "1.11.23", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.23.tgz", + "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.1.tgz", + "integrity": "sha512-+17vil3EVQRzvtDJSFuTWEb8XJRvXqAiV3qZyQWD398QeXUa6CxsUyMdD1fxzEhUrd4FojitFz7lhIHBTlV4fw==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.14.tgz", + "integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "license": "MIT" + }, + "node_modules/es-toolkit": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.51.0.tgz", + "integrity": "sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks", + "tests/types", + "tests/browser-compat" + ] + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, + "node_modules/fastdom": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastdom/-/fastdom-1.0.12.tgz", + "integrity": "sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==", + "license": "MIT", + "dependencies": { + "strictdom": "^1.0.1" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/find-process": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-2.1.1.tgz", + "integrity": "sha512-SrQDx3QhlmHM90iqn9rdjCQcw/T+WlpOkHFsjoRgB+zTpDfltNA1VSNYeYELwhUTJy12UFxqjWhmhOrJc+o4sA==", + "license": "MIT", + "dependencies": { + "chalk": "~4.1.2", + "commander": "^14.0.3", + "loglevel": "^1.9.2" + }, + "bin": { + "find-process": "dist/cjs/bin/find-process.js" + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.2" + } + }, + "node_modules/fontkitten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz", + "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==", + "license": "MIT", + "dependencies": { + "tiny-inflate": "^1.0.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "5.0.0-beta.4", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", + "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "engines": { + "node": ">=20.20.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-4.0.0.tgz", + "integrity": "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/magic-string": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.2.tgz", + "integrity": "sha512-veT/+7iXrXzT39XnEN4lOxtNl72dMgJ8Lp+5Bd6YcMSWpb0n0MjBM8Uuooi6jgJr8dhUW2swQgBmoZVMni5SVg==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz", + "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, + "node_modules/mermaid": { + "version": "11.17.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.17.0.tgz", + "integrity": "sha512-Jo9N377Wb4MSnHFPTbLi2SxFpsQl4eVHoxnW5U1Md9EazvgMp3s+4ohDxr81YNTgbn5Kj7HJ3yslrSJ52kwpbA==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.2", + "@iconify/utils": "^3.0.2", + "@mermaid-js/parser": "^1.2.1", + "@types/d3": "^7.4.3", + "@upsetjs/venn.js": "^2.0.0", + "cytoscape": "^3.34.0", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.14", + "dayjs": "^1.11.21", + "dompurify": "^3.3.3", + "es-toolkit": "^1.45.1", + "fastdom": "1.0.12", + "katex": "^0.16.47", + "khroma": "^2.1.0", + "marked": "^16.3.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neotraverse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-1.0.1.tgz", + "integrity": "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-mock-http": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.5.tgz", + "integrity": "sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/ohash": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.12.tgz", + "integrity": "sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==", + "license": "MIT" + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/p-limit": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.1.tgz", + "integrity": "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.2.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", + "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.4", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "license": "MIT" + }, + "node_modules/pagefind": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.5.2.tgz", + "integrity": "sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q==", + "dev": true, + "license": "MIT", + "bin": { + "pagefind": "lib/runner/bin.cjs" + }, + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.5.2", + "@pagefind/darwin-x64": "1.5.2", + "@pagefind/freebsd-x64": "1.5.2", + "@pagefind/linux-arm64": "1.5.2", + "@pagefind/linux-x64": "1.5.2", + "@pagefind/windows-arm64": "1.5.2", + "@pagefind/windows-x64": "1.5.2" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-ancestry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/process-ancestry/-/process-ancestry-0.1.0.tgz", + "integrity": "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.3.tgz", + "integrity": "sha512-gCaK+ndZ0hYezlqFegHFCVh2CQemsi0Npdh1qVM9bxlUFknjkbP6VmojWhddOCrbK0PbbacmYLWfTULRiT1eWA==", + "license": "MIT", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, + "node_modules/rolldown": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.5.tgz", + "integrity": "sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.146.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.5", + "@rolldown/binding-android-arm64": "1.2.5", + "@rolldown/binding-darwin-arm64": "1.2.5", + "@rolldown/binding-darwin-x64": "1.2.5", + "@rolldown/binding-freebsd-x64": "1.2.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.5", + "@rolldown/binding-linux-arm64-gnu": "1.2.5", + "@rolldown/binding-linux-arm64-musl": "1.2.5", + "@rolldown/binding-linux-ppc64-gnu": "1.2.5", + "@rolldown/binding-linux-s390x-gnu": "1.2.5", + "@rolldown/binding-linux-x64-gnu": "1.2.5", + "@rolldown/binding-linux-x64-musl": "1.2.5", + "@rolldown/binding-openharmony-arm64": "1.2.5", + "@rolldown/binding-win32-arm64-msvc": "1.2.5", + "@rolldown/binding-win32-x64-msvc": "1.2.5" + } + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/satteri": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.10.5.tgz", + "integrity": "sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.5", + "@types/hast": "^3.0.5", + "@types/mdast": "^4.0.4", + "@types/unist": "^3.0.3" + }, + "optionalDependencies": { + "@bruits/satteri-darwin-arm64": "0.10.5", + "@bruits/satteri-darwin-x64": "0.10.5", + "@bruits/satteri-linux-arm64-gnu": "0.10.5", + "@bruits/satteri-linux-arm64-musl": "0.10.5", + "@bruits/satteri-linux-x64-gnu": "0.10.5", + "@bruits/satteri-linux-x64-musl": "0.10.5", + "@bruits/satteri-wasm32-wasi": "0.10.5", + "@bruits/satteri-win32-arm64-msvc": "0.10.5", + "@bruits/satteri-win32-x64-msvc": "0.10.5" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/shiki": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/smol-toml": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", + "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strictdom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strictdom/-/strictdom-1.0.1.tgz", + "integrity": "sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==", + "license": "MIT" + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz", + "integrity": "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==", + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, + "node_modules/tinyclip": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.15.tgz", + "integrity": "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==", + "license": "MIT", + "engines": { + "node": "^16.14.0 || >= 17.3.0" + } + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-dedent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz", + "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz", + "integrity": "sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==", + "license": "MIT" + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz", + "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==", + "license": "MIT", + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.5.tgz", + "integrity": "sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.1.0", + "ohash": "^2.0.11", + "undici": "^8.0.0" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/uuid": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz", + "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "license": "MIT" + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..823acc1 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "t3code-decoded", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "A source-grounded, interactive architecture book for pingdotgg/t3code.", + "author": "Ahmed Alaa (https://github.com/BenAlaa)", + "license": "SEE LICENSE IN LICENSE", + "repository": { + "type": "git", + "url": "git+https://github.com/BenAlaa/t3code-decoded.git" + }, + "homepage": "https://benalaa.github.io/t3code-decoded/", + "bugs": { + "url": "https://github.com/BenAlaa/t3code-decoded/issues" + }, + "scripts": { + "dev": "ASTRO_TELEMETRY_DISABLED=1 astro dev", + "build": "npm run validate && ASTRO_TELEMETRY_DISABLED=1 astro build && node scripts/build-search-index.mjs && node scripts/validate-built-site.mjs", + "preview": "ASTRO_TELEMETRY_DISABLED=1 astro preview", + "validate": "node scripts/validate-book.mjs && node scripts/validate-sources.mjs", + "source:sync": "node scripts/sync-source-excerpts.mjs", + "source:check": "node scripts/sync-source-excerpts.mjs --check && node scripts/inventory-source.mjs --check", + "test": "node --test tests/*.test.mjs", + "check": "npm run test && npm run build" + }, + "dependencies": { + "@astrojs/mdx": "7.0.7", + "astro": "7.2.4", + "mermaid": "11.17.0" + }, + "devDependencies": { + "pagefind": "1.5.2", + "typescript": "6.0.3" + }, + "engines": { + "node": ">=24.10.0" + } +} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..a319b93 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,32 @@ + + T3 Code Decoded octopus + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/build-search-index.mjs b/scripts/build-search-index.mjs new file mode 100644 index 0000000..d8a00ad --- /dev/null +++ b/scripts/build-search-index.mjs @@ -0,0 +1,16 @@ +import { spawnSync } from "node:child_process"; +import path from "node:path"; +import process from "node:process"; + +const executable = path.resolve( + "node_modules", + ".bin", + process.platform === "win32" ? "pagefind.cmd" : "pagefind", +); + +const result = spawnSync(executable, ["--site", "dist"], { + stdio: "inherit", +}); + +if (result.error) throw result.error; +if (result.status !== 0) process.exit(result.status ?? 1); diff --git a/scripts/export-source-lock.mjs b/scripts/export-source-lock.mjs new file mode 100644 index 0000000..9dfac82 --- /dev/null +++ b/scripts/export-source-lock.mjs @@ -0,0 +1,9 @@ +import { readFile } from "node:fs/promises"; + +const lock = JSON.parse(await readFile(new URL("../sources/t3code.lock.json", import.meta.url), "utf8")); + +if (!/^[0-9a-f]{40}$/.test(lock.commit)) { + throw new Error("The source lock does not contain a valid immutable commit"); +} + +process.stdout.write(`commit=${lock.commit}\n`); diff --git a/scripts/inventory-source.mjs b/scripts/inventory-source.mjs new file mode 100644 index 0000000..b0d3841 --- /dev/null +++ b/scripts/inventory-source.mjs @@ -0,0 +1,65 @@ +import { execFileSync } from "node:child_process"; +import { readFile } from "node:fs/promises"; +import path from "node:path"; +import process from "node:process"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const lock = JSON.parse(await readFile(path.join(root, "sources/t3code.lock.json"), "utf8")); +const sourceRoot = path.resolve(process.env.T3CODE_SOURCE_DIR || path.join(root, lock.sourceDirHint)); +const commit = execFileSync("git", ["-C", sourceRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim(); +if (commit !== lock.commit) throw new Error(`T3 Code source mismatch: expected ${lock.commit}, found ${commit}`); + +const extensions = new Set([ + ".astro", ".bash", ".c", ".cc", ".cjs", ".cpp", ".css", ".cts", ".h", ".hpp", + ".java", ".js", ".jsx", ".kt", ".kts", ".m", ".mjs", ".mm", ".mts", ".ps1", + ".rs", ".scss", ".sh", ".sql", ".swift", ".ts", ".tsx", ".zsh", +]); +const excludedPrefixes = [".repos/", "assets/"]; +const testPattern = /(?:^|\/)(?:__mocks__|__tests__|fixtures|test|tests)(?:\/|$)|(?:\.|_)(?:spec|test)\.[^.]+$|Tests?\.swift$/i; +const tracked = execFileSync("git", ["-C", sourceRoot, "ls-tree", "-r", "--name-only", "-z", lock.commit], { + encoding: "utf8", + maxBuffer: 32 * 1024 * 1024, +}).split("\0").filter(Boolean); +const sourceFiles = tracked.filter((file) => !excludedPrefixes.some((prefix) => file.startsWith(prefix)) && extensions.has(path.extname(file))); +const testFiles = sourceFiles.filter((file) => testPattern.test(file)); +const productionFiles = sourceFiles.filter((file) => !testPattern.test(file)); + +const countLines = (files) => { + let count = 0; + for (let index = 0; index < files.length; index += 100) { + const chunk = files.slice(index, index + 100); + let output = ""; + try { + output = execFileSync("git", ["-C", sourceRoot, "grep", "-I", "-c", "-e", "^", lock.commit, "--", ...chunk], { + encoding: "utf8", + maxBuffer: 16 * 1024 * 1024, + }); + } catch (error) { + if (error.status !== 1) throw error; + output = error.stdout?.toString() ?? ""; + } + for (const line of output.trim().split("\n").filter(Boolean)) { + const separator = line.lastIndexOf(":"); + count += Number(line.slice(separator + 1)); + } + } + return count; +}; + +const report = { + inventoryRulesVersion: 1, + productionFiles: productionFiles.length, + productionLines: countLines(productionFiles), + testFiles: testFiles.length, + testLines: countLines(testFiles), +}; + +if (process.argv.includes("--check")) { + for (const [key, value] of Object.entries(report)) { + if (lock[key] !== value) throw new Error(`Source inventory drift for ${key}: lock=${lock[key]}, actual=${value}`); + } + process.stdout.write(`Verified ${report.productionFiles} production and ${report.testFiles} test source files.\n`); +} else { + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); +} diff --git a/scripts/lib/change-metadata.mjs b/scripts/lib/change-metadata.mjs new file mode 100644 index 0000000..28d54e3 --- /dev/null +++ b/scripts/lib/change-metadata.mjs @@ -0,0 +1,34 @@ +const conventionalHeader = /^(?:build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(?:\([a-z0-9][a-z0-9._/-]*\))?!?: \S(?:.*\S)?$/; + +export const validateConventionalHeader = (header, label = "change") => { + if (typeof header !== "string" || !conventionalHeader.test(header)) { + return `${label} must use '(): ' Conventional Commits syntax`; + } + if (header.length > 100) return `${label} must be at most 100 characters`; + return undefined; +}; + +const requiredSections = ["Outcome", "Scope", "Evidence", "Validation", "Review focus"]; + +export const validatePullRequestBody = (body) => { + if (typeof body !== "string" || !body.trim()) return ["pull request body is required"]; + + const withoutComments = body.replace(//g, ""); + const failures = []; + for (const section of requiredSections) { + const heading = new RegExp(`^## ${section.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*$`, "m"); + const match = heading.exec(withoutComments); + if (!match) { + failures.push(`pull request body is missing '## ${section}'`); + continue; + } + const contentStart = match.index + match[0].length; + const nextHeading = withoutComments.slice(contentStart).search(/^##\s+/m); + const content = withoutComments + .slice(contentStart, nextHeading === -1 ? undefined : contentStart + nextHeading) + .replace(/^#{3,6}\s+.*$/gm, "") + .trim(); + if (!content) failures.push(`pull request section '## ${section}' needs a concrete entry`); + } + return failures; +}; diff --git a/scripts/lib/git-source.mjs b/scripts/lib/git-source.mjs new file mode 100644 index 0000000..fac28b4 --- /dev/null +++ b/scripts/lib/git-source.mjs @@ -0,0 +1,24 @@ +import { execFileSync } from "node:child_process"; +import path from "node:path"; + +export const assertSafeGitPath = (value) => { + if (!value || path.isAbsolute(value) || value.split(/[\\/]/).includes("..") || value.includes("\0")) { + throw new Error(`Unsafe Git source path: ${value}`); + } + return value.replaceAll("\\", "/"); +}; + +export const readGitBlob = (repository, commit, file) => { + const safe = assertSafeGitPath(file); + return execFileSync("git", ["-C", repository, "show", `${commit}:${safe}`], { + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }); +}; + +export const gitObjectType = (repository, commit, sourcePath) => { + const safe = assertSafeGitPath(sourcePath); + return execFileSync("git", ["-C", repository, "cat-file", "-t", `${commit}:${safe}`], { + encoding: "utf8", + }).trim(); +}; diff --git a/scripts/lib/html-document.mjs b/scripts/lib/html-document.mjs new file mode 100644 index 0000000..57a4774 --- /dev/null +++ b/scripts/lib/html-document.mjs @@ -0,0 +1,11 @@ +export const collectHtmlIds = (html) => [...html.matchAll(/\sid=["']([^"']+)["']/g)].map((match) => match[1]); + +export const findDuplicateHtmlIds = (html) => { + const seen = new Set(); + const duplicates = new Set(); + for (const id of collectHtmlIds(html)) { + if (seen.has(id)) duplicates.add(id); + seen.add(id); + } + return [...duplicates].sort(); +}; diff --git a/scripts/sync-source-excerpts.mjs b/scripts/sync-source-excerpts.mjs new file mode 100644 index 0000000..ef614f3 --- /dev/null +++ b/scripts/sync-source-excerpts.mjs @@ -0,0 +1,65 @@ +import { createHash } from "node:crypto"; +import { execFileSync } from "node:child_process"; +import { readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; +import process from "node:process"; +import { fileURLToPath } from "node:url"; +import { gitObjectType, readGitBlob } from "./lib/git-source.mjs"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const lock = JSON.parse(await readFile(path.join(root, "sources/t3code.lock.json"), "utf8")); +const manifest = JSON.parse(await readFile(path.join(root, "sources/excerpts.manifest.json"), "utf8")); +const references = JSON.parse(await readFile(path.join(root, "sources/references.manifest.json"), "utf8")); +const sourceRoot = path.resolve(process.env.T3CODE_SOURCE_DIR || path.join(root, lock.sourceDirHint)); +const destination = path.join(root, "src/generated/excerpts.json"); + +const actualCommit = execFileSync("git", ["-C", sourceRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim(); +if (actualCommit !== lock.commit) { + throw new Error(`T3 Code source mismatch: expected ${lock.commit}, found ${actualCommit} at ${sourceRoot}`); +} + +const output = {}; +for (const item of manifest) { + if (output[item.id]) throw new Error(`Duplicate excerpt id: ${item.id}`); + const raw = readGitBlob(sourceRoot, lock.commit, item.path); + const lines = raw.replace(/\r\n/g, "\n").split("\n"); + if (!Number.isInteger(item.start) || !Number.isInteger(item.end) || item.start < 1 || item.end < item.start || item.end > lines.length) { + throw new Error(`Invalid range for ${item.id}: ${item.path}:${item.start}-${item.end} (file has ${lines.length} lines)`); + } + const code = lines.slice(item.start - 1, item.end).join("\n"); + output[item.id] = { + ...item, + code, + checksum: createHash("sha256").update(code).digest("hex"), + }; +} + +const referenceIds = new Set(Object.keys(output)); +for (const item of references) { + if (referenceIds.has(item.id)) throw new Error(`Duplicate source reference id: ${item.id}`); + referenceIds.add(item.id); + if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(item.id)) throw new Error(`Invalid source reference id: ${item.id}`); + const objectType = gitObjectType(sourceRoot, lock.commit, item.path); + if (item.kind === "directory") { + if (objectType !== "tree") throw new Error(`Expected source directory: ${item.path}`); + if (item.start || item.end) throw new Error(`Directory reference cannot have line numbers: ${item.id}`); + continue; + } + if (item.kind !== "file" || objectType !== "blob") throw new Error(`Expected source file: ${item.path}`); + if (item.start !== undefined || item.end !== undefined) { + const lines = readGitBlob(sourceRoot, lock.commit, item.path).replace(/\r\n/g, "\n").split("\n"); + if (!Number.isInteger(item.start) || !Number.isInteger(item.end) || item.start < 1 || item.end < item.start || item.end > lines.length) { + throw new Error(`Invalid reference range for ${item.id}: ${item.path}:${item.start}-${item.end}`); + } + } +} + +const serialized = `${JSON.stringify(output, null, 2)}\n`; +if (process.argv.includes("--check")) { + const current = await readFile(destination, "utf8").catch(() => ""); + if (current !== serialized) throw new Error("Generated excerpts are stale. Run npm run source:sync."); + process.stdout.write(`Verified ${manifest.length} excerpts and ${references.length} references against ${lock.shortCommit}.\n`); +} else { + await writeFile(destination, serialized); + process.stdout.write(`Wrote ${manifest.length} excerpts and verified ${references.length} references from ${lock.shortCommit}.\n`); +} diff --git a/scripts/validate-book.mjs b/scripts/validate-book.mjs new file mode 100644 index 0000000..ff34c95 --- /dev/null +++ b/scripts/validate-book.mjs @@ -0,0 +1,74 @@ +import { readdir, readFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const contentRoot = path.join(root, "src/content/book"); +const generated = JSON.parse(await readFile(path.join(root, "src/generated/excerpts.json"), "utf8")); +const excerptManifest = JSON.parse(await readFile(path.join(root, "sources/excerpts.manifest.json"), "utf8")); +const referenceManifest = JSON.parse(await readFile(path.join(root, "sources/references.manifest.json"), "utf8")); +const sourceIds = new Set([...excerptManifest, ...referenceManifest].map((item) => item.id)); +const files = (await readdir(contentRoot, { recursive: true })) + .filter((file) => /\.mdx?$/.test(file)) + .sort(); +const slugs = new Map(); +const orders = new Map(); +let sourceUses = 0; +let referenceUses = 0; + +for (const file of files) { + const raw = await readFile(path.join(contentRoot, file), "utf8"); + const slug = raw.match(/^slug:\s*["']?([^\n"']+)/m)?.[1]?.trim(); + const orderRaw = raw.match(/^order:\s*(\d+)/m)?.[1]; + const status = raw.match(/^status:\s*([^\n]+)/m)?.[1]?.trim(); + const gatesRaw = raw.match(/^gates:\s*\[([^\]]*)\]/m)?.[1] ?? ""; + const gates = new Set(gatesRaw.split(",").map((gate) => gate.trim()).filter(Boolean)); + if (!slug || orderRaw === undefined) throw new Error(`${file} is missing slug or order frontmatter.`); + const order = Number(orderRaw); + if (slugs.has(slug)) throw new Error(`Duplicate slug '${slug}' in ${slugs.get(slug)} and ${file}`); + if (orders.has(order)) throw new Error(`Duplicate order '${order}' in ${orders.get(order)} and ${file}`); + slugs.set(slug, file); + orders.set(order, file); + if (status === "source-checked" && !gates.has("sources")) throw new Error(`${file} is source-checked without the sources gate.`); + if (status === "verified" && ["sources", "links", "interaction", "editorial"].some((gate) => !gates.has(gate))) { + throw new Error(`${file} is verified without every review gate.`); + } + for (const match of raw.matchAll(/]*id=["']([^"']+)["']/g)) { + sourceUses += 1; + if (!generated[match[1]]) throw new Error(`${file} references unknown source excerpt '${match[1]}'.`); + } + for (const match of raw.matchAll(/sourceId:\s*["']([^"']+)["']/g)) { + referenceUses += 1; + if (!sourceIds.has(match[1])) throw new Error(`${file} references unknown source id '${match[1]}'.`); + } + for (const block of raw.matchAll(/sourceIds:\s*\[([\s\S]*?)\]/g)) { + const idsInBlock = [...block[1].matchAll(/["']([^"']+)["']/g)].map((source) => source[1]); + if (idsInBlock.length === 0) throw new Error(`${file} has an empty sourceIds list.`); + for (const id of idsInBlock) { + referenceUses += 1; + if (!sourceIds.has(id)) throw new Error(`${file} references unknown source id '${id}'.`); + } + } + for (const list of raw.matchAll(//g)) { + const idsInList = [...list[1].matchAll(/["']([^"']+)["']/g)].map((match) => match[1]); + if (idsInList.length === 0) throw new Error(`${file} has an empty SourceList.`); + for (const id of idsInList) { + referenceUses += 1; + if (!sourceIds.has(id)) throw new Error(`${file} references unknown source id '${id}'.`); + } + } + for (const component of ["EvidenceClaim", "Figure"]) { + const pattern = new RegExp(`<${component}\\s+[\\s\\S]*?(?:refs|sources)=\\{\\[([\\s\\S]*?)\\]\\}[\\s\\S]*?>`, "g"); + for (const match of raw.matchAll(pattern)) { + const idsInComponent = [...match[1].matchAll(/["']([^"']+)["']/g)].map((source) => source[1]); + if (idsInComponent.length === 0) throw new Error(`${file} has ${component} without source references.`); + for (const id of idsInComponent) { + referenceUses += 1; + if (!sourceIds.has(id)) throw new Error(`${file} references unknown source id '${id}'.`); + } + } + } +} + +if (!slugs.has("cover")) throw new Error("Book content must include slug: cover."); +process.stdout.write(`Validated ${files.length} book entries, ${sourceUses} excerpts, and ${referenceUses} source references.\n`); diff --git a/scripts/validate-built-site.mjs b/scripts/validate-built-site.mjs new file mode 100644 index 0000000..4bac13b --- /dev/null +++ b/scripts/validate-built-site.mjs @@ -0,0 +1,56 @@ +import { access, readdir, readFile } from "node:fs/promises"; +import path from "node:path"; +import process from "node:process"; +import { fileURLToPath } from "node:url"; +import { collectHtmlIds, findDuplicateHtmlIds } from "./lib/html-document.mjs"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const dist = path.join(root, "dist"); +const rawBase = process.env.BASE_PATH || "/"; +const base = `/${rawBase.replace(/^\/+|\/+$/g, "")}${rawBase === "/" ? "" : "/"}`; +const siteUrl = process.env.SITE_URL?.replace(/\/+$/, ""); +const htmlFiles = (await readdir(dist, { recursive: true })) + .filter((file) => file.endsWith(".html")) + .sort(); +const failures = []; + +const targetFor = (url) => { + const clean = url.split(/[?#]/, 1)[0]; + if (!clean.startsWith("/")) return undefined; + if (!clean.startsWith(base)) { + failures.push(`root-relative URL escapes BASE_PATH '${base}': ${url}`); + return undefined; + } + const relative = clean.slice(base.length); + if (!relative) return "index.html"; + return relative.endsWith("/") ? `${relative}index.html` : relative; +}; + +for (const file of htmlFiles) { + const raw = await readFile(path.join(dist, file), "utf8"); + const ids = new Set(collectHtmlIds(raw)); + for (const id of findDuplicateHtmlIds(raw)) failures.push(`${file} repeats id '${id}'`); + for (const match of raw.matchAll(/\s(?:href|src)=["']([^"']+)["']/g)) { + const url = match[1]; + if (/^(?:https?:|mailto:|tel:|data:|javascript:)/i.test(url)) continue; + if (url.startsWith("#")) { + if (url.length > 1 && !ids.has(decodeURIComponent(url.slice(1)))) failures.push(`${file} has missing local anchor ${url}`); + continue; + } + const target = targetFor(url); + if (!target) continue; + await access(path.join(dist, target)).catch(() => failures.push(`${file} links to missing ${url}`)); + } + if (siteUrl && file !== "404.html") { + const canonical = raw.match(/ failures.push("Pagefind runtime is missing")); +if (!htmlFiles.includes("404.html")) failures.push("404.html is missing"); + +if (failures.length) throw new Error(`Built-site validation failed:\n- ${[...new Set(failures)].join("\n- ")}`); +process.stdout.write(`Validated ${htmlFiles.length} built pages at base '${base}'.\n`); diff --git a/scripts/validate-change-metadata.mjs b/scripts/validate-change-metadata.mjs new file mode 100644 index 0000000..bd7c466 --- /dev/null +++ b/scripts/validate-change-metadata.mjs @@ -0,0 +1,25 @@ +import { execFileSync } from "node:child_process"; +import { validateConventionalHeader, validatePullRequestBody } from "./lib/change-metadata.mjs"; + +const { PR_TITLE, PR_BODY, BASE_SHA, HEAD_SHA } = process.env; +const failures = []; + +if (!BASE_SHA || !HEAD_SHA || !/^[0-9a-f]{40}$/i.test(BASE_SHA) || !/^[0-9a-f]{40}$/i.test(HEAD_SHA)) { + failures.push("pull request base and head revisions must be available"); +} else { + const subjects = execFileSync("git", ["log", "--format=%s", `${BASE_SHA}..${HEAD_SHA}`], { encoding: "utf8" }) + .split("\n") + .filter(Boolean); + if (!subjects.length) failures.push("pull request must contain at least one commit"); + for (const subject of subjects) { + const failure = validateConventionalHeader(subject, `commit '${subject}'`); + if (failure) failures.push(failure); + } +} + +const titleFailure = validateConventionalHeader(PR_TITLE, "pull request title"); +if (titleFailure) failures.push(titleFailure); +failures.push(...validatePullRequestBody(PR_BODY)); + +if (failures.length) throw new Error(`Change-metadata validation failed:\n- ${[...new Set(failures)].join("\n- ")}`); +process.stdout.write("Validated the pull request title, body, and commit subjects.\n"); diff --git a/scripts/validate-sources.mjs b/scripts/validate-sources.mjs new file mode 100644 index 0000000..899bd38 --- /dev/null +++ b/scripts/validate-sources.mjs @@ -0,0 +1,101 @@ +import { createHash } from "node:crypto"; +import { readFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const lock = JSON.parse(await readFile(path.join(root, "sources/t3code.lock.json"), "utf8")); +const manifest = JSON.parse(await readFile(path.join(root, "sources/excerpts.manifest.json"), "utf8")); +const references = JSON.parse(await readFile(path.join(root, "sources/references.manifest.json"), "utf8")); +const generated = JSON.parse(await readFile(path.join(root, "src/generated/excerpts.json"), "utf8")); +const ids = new Set(); +const idPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/; +const commitPattern = /^[0-9a-f]{40}$/; +const shortCommitPattern = /^[0-9a-f]{7,12}$/; + +const isSafeSourcePath = (value) => + typeof value === "string" && + value.length > 0 && + !path.isAbsolute(value) && + !value.split(/[\\/]/).includes("..") && + !value.includes("\\") && + !/[\0\r\n]/.test(value); + +const validateRange = (item, kind = "excerpt") => { + if (!Number.isInteger(item.start) || !Number.isInteger(item.end) || item.start < 1 || item.end < item.start) { + throw new Error(`Invalid source ${kind} range: ${item.id}`); + } +}; + +if (!/^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/?$/.test(lock.repository)) { + throw new Error(`Invalid source repository URL: ${lock.repository}`); +} +if (!commitPattern.test(lock.commit)) throw new Error(`Invalid locked source commit: ${lock.commit}`); +if (!shortCommitPattern.test(lock.shortCommit) || !lock.commit.startsWith(lock.shortCommit)) { + throw new Error(`shortCommit does not match the locked source commit: ${lock.shortCommit}`); +} +if (typeof lock.branch !== "string" || !lock.branch.trim() || /[\0\r\n]/.test(lock.branch)) { + throw new Error("Invalid locked source branch"); +} +if (typeof lock.capturedAt !== "string" || !Number.isFinite(Date.parse(lock.capturedAt))) { + throw new Error(`Invalid source capture timestamp: ${lock.capturedAt}`); +} +if (typeof lock.sourceDirHint !== "string" || !lock.sourceDirHint.trim() || path.isAbsolute(lock.sourceDirHint) || /[\0\r\n]/.test(lock.sourceDirHint)) { + throw new Error("Invalid local source directory hint"); +} +for (const key of ["inventoryRulesVersion", "productionFiles", "productionLines", "testFiles", "testLines"]) { + if (!Number.isInteger(lock[key]) || lock[key] < 1) throw new Error(`Invalid source lock count: ${key}`); +} +if (typeof lock.notes !== "string" || !lock.notes.trim()) throw new Error("Source lock notes must explain the inventory boundary"); + +if (!Array.isArray(manifest)) throw new Error("Excerpt manifest must be an array"); +if (!Array.isArray(references)) throw new Error("Reference manifest must be an array"); +if (!generated || Array.isArray(generated) || typeof generated !== "object") { + throw new Error("Generated excerpts must be an object keyed by source id"); +} + +for (const item of manifest) { + if (!idPattern.test(item.id)) throw new Error(`Invalid source excerpt id: ${item.id}`); + if (ids.has(item.id)) throw new Error(`Duplicate source id: ${item.id}`); + ids.add(item.id); + if (!isSafeSourcePath(item.path)) throw new Error(`Unsafe source path: ${item.path}`); + validateRange(item); + if (typeof item.language !== "string" || !item.language.trim() || typeof item.label !== "string" || !item.label.trim()) { + throw new Error(`Invalid source excerpt metadata: ${item.id}`); + } + const record = generated[item.id]; + if (!record) throw new Error(`Missing generated excerpt: ${item.id}`); + for (const key of ["id", "path", "start", "end", "language", "label"]) { + if (record[key] !== item[key]) throw new Error(`Generated metadata drift for ${item.id}.${key}`); + } + if (typeof record.code !== "string" || !/^[0-9a-f]{64}$/.test(record.checksum)) { + throw new Error(`Invalid generated excerpt payload: ${item.id}`); + } + const checksum = createHash("sha256").update(record.code).digest("hex"); + if (checksum !== record.checksum) throw new Error(`Checksum mismatch for ${item.id}`); + const lineCount = record.code.split("\n").length; + if (lineCount !== item.end - item.start + 1) throw new Error(`Line count mismatch for ${item.id}`); +} + +const extras = Object.keys(generated).filter((id) => !ids.has(id)); +if (extras.length) throw new Error(`Generated excerpts not in manifest: ${extras.join(", ")}`); + +for (const item of references) { + if (ids.has(item.id)) throw new Error(`Duplicate source id across manifests: ${item.id}`); + ids.add(item.id); + if (!idPattern.test(item.id)) throw new Error(`Invalid source reference id: ${item.id}`); + if (!isSafeSourcePath(item.path)) throw new Error(`Unsafe source path: ${item.path}`); + if (typeof item.label !== "string" || !item.label.trim() || !["file", "directory"].includes(item.kind)) { + throw new Error(`Invalid source reference metadata: ${item.id}`); + } + if (item.kind === "directory" && (item.start !== undefined || item.end !== undefined)) { + throw new Error(`Directory reference has line numbers: ${item.id}`); + } + if (item.kind === "file" && (item.start !== undefined || item.end !== undefined)) { + validateRange(item, "reference"); + } +} + +process.stdout.write( + `Validated source lock ${lock.shortCommit}, ${manifest.length} excerpts, and ${references.length} pinned source references.\n`, +); diff --git a/sources/excerpts.manifest.json b/sources/excerpts.manifest.json new file mode 100644 index 0000000..f39f958 --- /dev/null +++ b/sources/excerpts.manifest.json @@ -0,0 +1,1474 @@ +[ + { + "id": "architecture-boundary", + "path": "docs/internals/overview.md", + "start": 5, + "end": 28, + "language": "markdown", + "label": "The execution boundary" + }, + { + "id": "orchestration-rpc-methods", + "path": "packages/contracts/src/orchestration.ts", + "start": 27, + "end": 36, + "language": "typescript", + "label": "Orchestration RPC surface" + }, + { + "id": "turn-start-command", + "path": "packages/contracts/src/orchestration.ts", + "start": 847, + "end": 864, + "language": "typescript", + "label": "Client turn-start command" + }, + { + "id": "provider-adapter-core", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 47, + "end": 71, + "language": "typescript", + "label": "Provider adapter lifecycle contract" + }, + { + "id": "provider-adapter-interactions", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 73, + "end": 94, + "language": "typescript", + "label": "Provider approval and input contract" + }, + { + "id": "provider-adapter-stream", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 126, + "end": 134, + "language": "typescript", + "label": "Canonical provider event stream" + }, + { + "id": "orchestration-transaction", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 197, + "end": 259, + "language": "typescript", + "label": "Atomic command commit" + }, + { + "id": "orchestration-dispatch", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 331, + "end": 368, + "language": "typescript", + "label": "Serialized command dispatch and event fan-out" + }, + { + "id": "server-runtime-core", + "path": "apps/server/src/server.ts", + "start": 353, + "end": 416, + "language": "typescript", + "label": "Authentication, remote endpoint, provider, and server dependency assembly" + }, + { + "id": "dispatch-result", + "path": "packages/contracts/src/orchestration.ts", + "start": 1580, + "end": 1583, + "language": "typescript", + "label": "Successful client dispatch result" + }, + { + "id": "rejected-receipt-best-effort", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 287, + "end": 325, + "language": "typescript", + "label": "Best-effort invariant-rejection receipt" + }, + { + "id": "hot-reactor-no-replay", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1405, + "end": 1409, + "language": "typescript", + "label": "Hot post-commit stream has no pending-work replay" + }, + { + "id": "cli-entry-command", + "path": "apps/server/src/bin.ts", + "start": 23, + "end": 71, + "language": "typescript", + "label": "Root CLI and subcommand dispatch" + }, + { + "id": "cli-config-precedence", + "path": "apps/server/src/cli/config.ts", + "start": 244, + "end": 280, + "language": "typescript", + "label": "Mode, port, and base-directory precedence" + }, + { + "id": "cli-serve-semantics", + "path": "apps/server/src/cli/server.ts", + "start": 21, + "end": 35, + "language": "typescript", + "label": "Start and headless serve semantics" + }, + { + "id": "startup-readiness-order", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 514, + "end": 548, + "language": "typescript", + "label": "Prepared, activated, command-ready, and ready order" + }, + { + "id": "command-readiness-middleware", + "path": "apps/server/src/server.ts", + "start": 431, + "end": 437, + "language": "typescript", + "label": "Global route-execution readiness barrier" + }, + { + "id": "rpc-stream-contracts", + "path": "packages/contracts/src/rpc.ts", + "start": 933, + "end": 948, + "language": "typescript", + "label": "Typed shell and thread streaming RPC contracts" + }, + { + "id": "thread-resume-race", + "path": "apps/server/src/ws.ts", + "start": 1394, + "end": 1521, + "language": "typescript", + "label": "Attach-before-read and bounded thread replay" + }, + { + "id": "auth-credential-precedence", + "path": "apps/server/src/auth/EnvironmentAuth.ts", + "start": 592, + "end": 632, + "language": "typescript", + "label": "Cookie, Bearer, and DPoP authentication precedence" + }, + { + "id": "websocket-ticket-verification", + "path": "apps/server/src/auth/SessionStore.ts", + "start": 785, + "end": 851, + "language": "typescript", + "label": "WebSocket ticket verification reloads session state" + }, + { + "id": "command-union-boundary", + "path": "packages/contracts/src/orchestration.ts", + "start": 913, + "end": 1057, + "language": "typescript", + "label": "Client-dispatchable, normalized, and trusted internal command unions" + }, + { + "id": "normalizer-staging-boundary", + "path": "apps/server/src/orchestration/Normalizer.ts", + "start": 18, + "end": 179, + "language": "typescript", + "label": "Pre-transaction timestamp, workspace, and attachment staging" + }, + { + "id": "turn-atomic-batch", + "path": "apps/server/src/orchestration/decider.ts", + "start": 926, + "end": 1036, + "language": "typescript", + "label": "Existing-thread turn plans a two-to-four-event batch" + }, + { + "id": "engine-commit-publication", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 197, + "end": 259, + "language": "typescript", + "label": "SQL commit followed by in-memory fold and hot publication" + }, + { + "id": "command-receipt-schema", + "path": "apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts", + "start": 25, + "end": 33, + "language": "typescript", + "label": "Durable command receipt fields" + }, + { + "id": "projection-transaction-cursor", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1609, + "end": 1678, + "language": "typescript", + "label": "Ordered projectors, transactional cursor updates, and attachment side effects" + }, + { + "id": "snapshot-safe-watermark", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 195, + "end": 258, + "language": "typescript", + "label": "Snapshot watermark is the minimum required projector cursor" + }, + { + "id": "provider-reactor-forked-send", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1060, + "end": 1174, + "language": "typescript", + "label": "Volatile turn dedupe and forked provider send" + }, + { + "id": "sqlite-runtime-pragmas", + "path": "apps/server/src/persistence/Layers/Sqlite.ts", + "start": 24, + "end": 66, + "language": "typescript", + "label": "SQLite runtime selection, pragmas, migrations, and scoped layers" + }, + { + "id": "provider-instance-identity-contract", + "path": "packages/contracts/src/providerInstance.ts", + "start": 4, + "end": 32, + "language": "typescript", + "label": "Driver kind and configured instance identity" + }, + { + "id": "provider-driver-instance-spi", + "path": "apps/server/src/provider/ProviderDriver.ts", + "start": 55, + "end": 117, + "language": "typescript", + "label": "Scoped provider driver and instance records" + }, + { + "id": "provider-driver-instance-records", + "path": "apps/server/src/provider/ProviderDriver.ts", + "start": 4, + "end": 20, + "language": "typescript", + "label": "Plain provider driver and instance record contracts" + }, + { + "id": "codex-app-server-client-typed-stdio", + "path": "packages/effect-codex-app-server/src/client.ts", + "start": 140, + "end": 211, + "language": "typescript", + "label": "Typed Codex notifications, requests, and transport calls" + }, + { + "id": "codex-adapter-session-runtime", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1642, + "end": 1693, + "language": "typescript", + "label": "Codex session replacement and runtime configuration" + }, + { + "id": "codex-adapter-runtime-events", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1000, + "end": 1084, + "language": "typescript", + "label": "Codex usage, turn, and plan event normalization" + }, + { + "id": "claude-adapter-query-config", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4138, + "end": 4196, + "language": "typescript", + "label": "Claude permission mapping and query option assembly" + }, + { + "id": "claude-query-invocation", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4223, + "end": 4235, + "language": "typescript", + "label": "Claude SDK query invocation" + }, + { + "id": "claude-adapter-interaction-handlers", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4497, + "end": 4529, + "language": "typescript", + "label": "Claude approval and structured-input deferreds" + }, + { + "id": "acp-client-typed-surface", + "path": "packages/effect-acp/src/client.ts", + "start": 40, + "end": 134, + "language": "typescript", + "label": "Typed ACP session command surface" + }, + { + "id": "cursor-session-mode-selection", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 217, + "end": 294, + "language": "typescript", + "label": "Cursor negotiated mode and model selection" + }, + { + "id": "grok-acp-runtime-support", + "path": "apps/server/src/provider/acp/GrokAcpSupport.ts", + "start": 31, + "end": 108, + "language": "typescript", + "label": "Grok ACP launch, authentication, and model selection" + }, + { + "id": "opencode-runtime-ownership", + "path": "apps/server/src/provider/opencodeRuntime.ts", + "start": 140, + "end": 177, + "language": "typescript", + "label": "Local and external OpenCode server ownership" + }, + { + "id": "opencode-turn-and-revert", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1430, + "end": 1509, + "language": "typescript", + "label": "OpenCode prompt and steering path" + }, + { + "id": "usage-live-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 309, + "end": 331, + "language": "typescript", + "label": "Live thread token-usage snapshot contract" + }, + { + "id": "usage-codex-normalization", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 159, + "end": 190, + "language": "typescript", + "label": "Codex live token-usage normalization" + }, + { + "id": "usage-codex-emission", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1000, + "end": 1018, + "language": "typescript", + "label": "Codex live usage event emission" + }, + { + "id": "usage-claude-emission", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 2051, + "end": 2088, + "language": "typescript", + "label": "Claude live usage event emission" + }, + { + "id": "usage-live-activity", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 766, + "end": 784, + "language": "typescript", + "label": "Live usage becomes context-window activity" + }, + { + "id": "usage-web-context-meter", + "path": "apps/web/src/lib/contextWindow.ts", + "start": 50, + "end": 96, + "language": "typescript", + "label": "Latest valid context-window snapshot derivation" + }, + { + "id": "usage-summary-contract", + "path": "packages/contracts/src/usage.ts", + "start": 1, + "end": 101, + "language": "typescript", + "label": "Historical usage version, providers, tokens, and cost buckets" + }, + { + "id": "usage-home-discovery", + "path": "apps/server/src/usage/UsageService.ts", + "start": 187, + "end": 225, + "language": "typescript", + "label": "Claude and Codex transcript home resolution" + }, + { + "id": "usage-transcript-parsers", + "path": "apps/server/src/usage/usageTranscripts.ts", + "start": 78, + "end": 137, + "language": "typescript", + "label": "Claude transcript usage normalization" + }, + { + "id": "usage-dedup-buckets", + "path": "apps/server/src/usage/usageAggregation.ts", + "start": 109, + "end": 178, + "language": "typescript", + "label": "Global deduplication, bounds, bucketing, and pricing fold" + }, + { + "id": "usage-pricing-cache", + "path": "apps/server/src/usage/usagePricing.ts", + "start": 85, + "end": 148, + "language": "typescript", + "label": "Historical usage rate lookup and pricing arithmetic" + }, + { + "id": "usage-rpc-contract", + "path": "packages/contracts/src/rpc.ts", + "start": 260, + "end": 284, + "language": "typescript", + "label": "Typed usage summary RPC" + }, + { + "id": "usage-environment-merge", + "path": "packages/shared/src/usageMerge.ts", + "start": 102, + "end": 163, + "language": "typescript", + "label": "Deterministic physical-source ownership across environments" + }, + { + "id": "usage-reader-failure-policy", + "path": "apps/server/src/usage/usageTranscriptReader.ts", + "start": 92, + "end": 140, + "language": "typescript", + "label": "Streaming transcript read and null-on-read-failure policy" + }, + { + "id": "usage-source-status", + "path": "apps/server/src/usage/UsageService.ts", + "start": 352, + "end": 408, + "language": "typescript", + "label": "Current historical source status and session accounting" + }, + { + "id": "project-root-normalization", + "path": "apps/server/src/workspace/WorkspacePaths.ts", + "start": 161, + "end": 200, + "language": "typescript", + "label": "Workspace-root resolution, validation, and opt-in creation" + }, + { + "id": "project-create-normalization", + "path": "apps/server/src/orchestration/Normalizer.ts", + "start": 55, + "end": 90, + "language": "typescript", + "label": "Project creation normalization before dispatch" + }, + { + "id": "project-root-uniqueness", + "path": "apps/server/src/orchestration/commandInvariants.ts", + "start": 75, + "end": 97, + "language": "typescript", + "label": "Active project workspace-root uniqueness invariant" + }, + { + "id": "project-t3-file-schema", + "path": "packages/contracts/src/t3ProjectFile.ts", + "start": 7, + "end": 94, + "language": "typescript", + "label": "Checked-in t3.json project configuration contract" + }, + { + "id": "project-t3-file-loader", + "path": "apps/server/src/project/T3ProjectFileLoader.ts", + "start": 42, + "end": 105, + "language": "typescript", + "label": "Best-effort t3.json loading and validation" + }, + { + "id": "project-t3-file-loader-tests", + "path": "apps/server/src/project/T3ProjectFileLoader.test.ts", + "start": 29, + "end": 88, + "language": "typescript", + "label": "t3.json JSONC, missing-file, and invalid-input tests" + }, + { + "id": "project-thread-env-precedence", + "path": "packages/shared/src/threadEnvMode.ts", + "start": 3, + "end": 35, + "language": "typescript", + "label": "Project, t3.json, and global thread-environment precedence" + }, + { + "id": "project-settings-inherited-default", + "path": "apps/web/src/components/settings/ProjectSettingsPanel.tsx", + "start": 475, + "end": 482, + "language": "tsx", + "label": "Inherited project environment default in web settings" + }, + { + "id": "project-settings-project-override", + "path": "apps/web/src/components/settings/ProjectSettingsPanel.tsx", + "start": 866, + "end": 905, + "language": "tsx", + "label": "Project environment override controls" + }, + { + "id": "project-repository-identity", + "path": "apps/server/src/project/RepositoryIdentityResolver.ts", + "start": 48, + "end": 166, + "language": "typescript", + "label": "Best-effort Git remote repository identity resolution" + }, + { + "id": "project-identity-read-projection", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 313, + "end": 388, + "language": "typescript", + "label": "Snapshot-time repository identity enrichment" + }, + { + "id": "project-durable-projection", + "path": "apps/server/src/orchestration/decider.ts", + "start": 227, + "end": 298, + "language": "typescript", + "label": "Project creation and metadata event decisions" + }, + { + "id": "project-projector", + "path": "apps/server/src/orchestration/projector.ts", + "start": 207, + "end": 263, + "language": "typescript", + "label": "Durable project read-model projection" + }, + { + "id": "project-logical-grouping", + "path": "packages/client-runtime/src/state/projectGrouping.ts", + "start": 67, + "end": 140, + "language": "typescript", + "label": "Client-side physical and logical project grouping" + }, + { + "id": "project-environment-label", + "path": "apps/web/src/sidebarProjectGrouping.ts", + "start": 53, + "end": 115, + "language": "typescript", + "label": "Environment labels retained in grouped sidebar projects" + }, + { + "id": "project-setup-script-selection", + "path": "packages/shared/src/projectScripts.ts", + "start": 11, + "end": 37, + "language": "typescript", + "label": "Worktree setup-script selection and environment construction" + }, + { + "id": "project-setup-script-runner", + "path": "apps/server/src/project/ProjectSetupScriptRunner.ts", + "start": 123, + "end": 183, + "language": "typescript", + "label": "Setup script launched in the linked worktree terminal" + }, + { + "id": "worktree-non-git-fallback", + "path": "apps/web/src/components/ChatView.logic.ts", + "start": 322, + "end": 327, + "language": "typescript", + "label": "Non-Git projects fall back from worktree to local mode" + }, + { + "id": "worktree-ref-occupancy", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2463, + "end": 2559, + "language": "typescript", + "label": "Git worktree listing decorates occupied branch references" + }, + { + "id": "worktree-create-remove-contract", + "path": "packages/contracts/src/git.ts", + "start": 124, + "end": 165, + "language": "typescript", + "label": "Worktree creation and removal RPC inputs" + }, + { + "id": "worktree-result-contract", + "path": "packages/contracts/src/git.ts", + "start": 264, + "end": 294, + "language": "typescript", + "label": "Worktree and pull-request preparation results" + }, + { + "id": "worktree-bootstrap-path", + "path": "apps/server/src/ws.ts", + "start": 979, + "end": 1022, + "language": "typescript", + "label": "Origin-aware worktree bootstrap saga" + }, + { + "id": "worktree-origin-base-test", + "path": "apps/server/src/vcs/GitVcsDriverCore.test.ts", + "start": 1505, + "end": 1565, + "language": "typescript", + "label": "Remote base reference worktree creation test" + }, + { + "id": "worktree-create-command", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2763, + "end": 2799, + "language": "typescript", + "label": "Git worktree add command and default linked path" + }, + { + "id": "worktree-setup-runner", + "path": "apps/server/src/project/ProjectSetupScriptRunner.ts", + "start": 123, + "end": 183, + "language": "typescript", + "label": "Post-creation setup script runner" + }, + { + "id": "worktree-setup-test", + "path": "apps/server/src/project/ProjectSetupScriptRunner.test.ts", + "start": 93, + "end": 152, + "language": "typescript", + "label": "Setup terminal cwd and environment test" + }, + { + "id": "worktree-remove-command", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2982, + "end": 2994, + "language": "typescript", + "label": "Git worktree removal command" + }, + { + "id": "worktree-create-remove-test", + "path": "apps/server/src/vcs/GitVcsDriverCore.test.ts", + "start": 1377, + "end": 1403, + "language": "typescript", + "label": "Worktree create and remove integration test" + }, + { + "id": "worktree-bootstrap-failure-cleanup", + "path": "apps/server/src/ws.ts", + "start": 1025, + "end": 1053, + "language": "typescript", + "label": "Bootstrap failure compensation for a newly created thread" + }, + { + "id": "turn-lifecycle-start-decider", + "path": "apps/server/src/orchestration/decider.ts", + "start": 926, + "end": 1036, + "language": "typescript", + "label": "Turn start intent and atomic lifecycle-reset event batch" + }, + { + "id": "turn-lifecycle-command-reactor", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1060, + "end": 1174, + "language": "typescript", + "label": "Committed turn intent forwarded to the provider" + }, + { + "id": "turn-lifecycle-runtime-correlation", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 195, + "end": 213, + "language": "typescript", + "label": "Provider runtime event identity validation" + }, + { + "id": "turn-lifecycle-runtime-guards", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1505, + "end": 1656, + "language": "typescript", + "label": "Runtime lifecycle correlation and durable session folding" + }, + { + "id": "turn-lifecycle-buffering", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1659, + "end": 1750, + "language": "typescript", + "label": "Buffered assistant delivery and pause-boundary flush" + }, + { + "id": "turn-lifecycle-interrupt", + "path": "apps/server/src/orchestration/decider.ts", + "start": 1039, + "end": 1058, + "language": "typescript", + "label": "Durable turn interrupt intent" + }, + { + "id": "turn-lifecycle-checkpoint-completion", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 356, + "end": 458, + "language": "typescript", + "label": "Post-turn checkpoint capture and placeholder replacement" + }, + { + "id": "permission-runtime-mode-contract", + "path": "packages/contracts/src/orchestration.ts", + "start": 120, + "end": 143, + "language": "typescript", + "label": "Canonical runtime modes and approval decisions" + }, + { + "id": "permission-codex-mode-map", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 268, + "end": 340, + "language": "typescript", + "label": "T3 runtime modes mapped into Codex approval and sandbox settings" + }, + { + "id": "permission-request-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 430, + "end": 469, + "language": "typescript", + "label": "Canonical approval and structured-input request payloads" + }, + { + "id": "work-task-usage-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 471, + "end": 543, + "language": "typescript", + "label": "Typed per-task usage and agent-versus-background classification" + }, + { + "id": "work-task-latest-activities", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 569, + "end": 646, + "language": "typescript", + "label": "Separate stable task progress and usage activity snapshots" + }, + { + "id": "work-subagent-usage-merge", + "path": "packages/client-runtime/src/state/subagentRuntime.ts", + "start": 149, + "end": 225, + "language": "typescript", + "label": "Tolerant field-wise task usage parsing and max merge" + }, + { + "id": "context-provider-binding-shape", + "path": "apps/server/src/persistence/ProviderSessionRuntime.ts", + "start": 35, + "end": 110, + "language": "typescript", + "label": "Persisted provider-instance binding and opaque continuation state" + }, + { + "id": "context-memory-compaction-ingestion", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 744, + "end": 763, + "language": "typescript", + "label": "Provider compaction observation becomes durable thread activity" + }, + { + "id": "context-window-reducer-retention", + "path": "packages/client-runtime/src/state/threadReducer.ts", + "start": 562, + "end": 592, + "language": "typescript", + "label": "Latest resolvable context-window snapshot retained per turn id" + }, + { + "id": "workbench-terminal-attach-order", + "path": "apps/server/src/terminal/Manager.ts", + "start": 2351, + "end": 2402, + "language": "typescript", + "label": "Terminal attach buffers races, emits a snapshot, then delivers live events" + }, + { + "id": "workbench-asset-token-verification", + "path": "apps/server/src/assets/AssetAccess.ts", + "start": 410, + "end": 451, + "language": "typescript", + "label": "Asset URL signing followed by signature and expiry verification" + }, + { + "id": "workbench-mcp-credential-issue", + "path": "apps/server/src/mcp/McpSessionRegistry.ts", + "start": 112, + "end": 168, + "language": "typescript", + "label": "Random MCP bearer credential and registry-generated scoped session identity" + }, + { + "id": "workbench-pr-write-gates", + "path": "apps/server/src/pullRequest/PullRequestService.ts", + "start": 1300, + "end": 1367, + "language": "typescript", + "label": "Pull-request host capability checks followed by fresh viewer authorization" + }, + { + "id": "project-script-import-flow", + "path": "apps/web/src/components/ProjectScriptsControl.tsx", + "start": 80, + "end": 150, + "language": "tsx", + "label": "Checked-in t3.json actions are deduplicated import suggestions" + }, + { + "id": "web-main-runtime-entry", + "path": "apps/web/src/main.tsx", + "start": 1, + "end": 61, + "language": "tsx", + "label": "Electron-aware history and authenticated React entry" + }, + { + "id": "web-app-root-providers", + "path": "apps/web/src/AppRoot.tsx", + "start": 1, + "end": 23, + "language": "tsx", + "label": "Shared atom registry and route-persistent renderer hosts" + }, + { + "id": "web-router-composition", + "path": "apps/web/src/router.ts", + "start": 1, + "end": 20, + "language": "typescript", + "label": "Generated route-tree router construction" + }, + { + "id": "web-environment-atom-catalog", + "path": "apps/web/src/connection/catalog.ts", + "start": 1, + "end": 5, + "language": "typescript", + "label": "Web environment catalog uses the shared atom runtime" + }, + { + "id": "web-environment-session-atoms", + "path": "apps/web/src/state/session.ts", + "start": 7, + "end": 41, + "language": "typescript", + "label": "Per-environment prepared connection and session atoms" + }, + { + "id": "web-timeline-list-virtualization", + "path": "apps/web/src/components/chat/MessagesTimeline.tsx", + "start": 570, + "end": 648, + "language": "tsx", + "label": "Keyed virtualized message timeline configuration" + }, + { + "id": "web-timeline-row-structural-sharing", + "path": "apps/web/src/components/chat/MessagesTimeline.tsx", + "start": 2095, + "end": 2113, + "language": "tsx", + "label": "Timeline row structural sharing for virtualized memo boundaries" + }, + { + "id": "web-sidebar-row-locality", + "path": "apps/web/src/components/Sidebar.tsx", + "start": 2200, + "end": 2252, + "language": "tsx", + "label": "Sidebar streaming row locality and callback references" + }, + { + "id": "web-client-tracing-export", + "path": "apps/web/src/observability/clientTracing.ts", + "start": 15, + "end": 96, + "language": "typescript", + "label": "Primary-environment OTLP client tracing lifecycle" + }, + { + "id": "web-sidebar-optimistic-pinning", + "path": "apps/web/src/components/Sidebar.tsx", + "start": 2554, + "end": 2610, + "language": "tsx", + "label": "Optimistic pin-order override and canonical surrender rules" + }, + { + "id": "mobile-app-root-composition", + "path": "apps/mobile/src/App.tsx", + "start": 61, + "end": 106, + "language": "tsx", + "label": "Mobile root Atom, provider, navigation, and native host composition" + }, + { + "id": "mobile-connection-runtime-layer", + "path": "apps/mobile/src/connection/runtime.ts", + "start": 1, + "end": 45, + "language": "typescript", + "label": "Shared connection and snapshot layers with mobile platform services" + }, + { + "id": "mobile-persistence-schema", + "path": "apps/mobile/src/persistence/mobile-database.ts", + "start": 242, + "end": 275, + "language": "typescript", + "label": "SQLite client cache and preference schema with versioned migration" + }, + { + "id": "mobile-draft-update-flush", + "path": "apps/mobile/src/state/use-composer-drafts.ts", + "start": 212, + "end": 229, + "language": "typescript", + "label": "Draft persistence flush before JavaScript runtime teardown" + }, + { + "id": "mobile-outbox-optimistic-durability", + "path": "apps/mobile/src/state/thread-outbox-manager.ts", + "start": 91, + "end": 124, + "language": "typescript", + "label": "Optimistic enqueue, durable rollback, and pre-delivery confirmation" + }, + { + "id": "mobile-outbox-delivery-policy", + "path": "apps/mobile/src/state/thread-outbox-model.ts", + "start": 145, + "end": 226, + "language": "typescript", + "label": "Outbox existence guards, capped backoff, and failure classification" + }, + { + "id": "mobile-share-commit-boundary", + "path": "apps/mobile/src/features/sharing/incoming-share-inbox.ts", + "start": 46, + "end": 124, + "language": "typescript", + "label": "Durable share inbox write before native handoff acknowledgement" + }, + { + "id": "mobile-native-surface-probe", + "path": "apps/mobile/src/features/terminal/nativeTerminalModule.ts", + "start": 48, + "end": 100, + "language": "typescript", + "label": "Optional native terminal resolution and compiled revision probe" + }, + { + "id": "mobile-update-restart-guard", + "path": "apps/mobile/src/features/updates/app-updates.ts", + "start": 417, + "end": 480, + "language": "typescript", + "label": "Deferred OTA flush and foreground-handoff safety gate" + }, + { + "id": "desktop-preload-bridge", + "path": "apps/desktop/src/preload.ts", + "start": 30, + "end": 103, + "language": "typescript", + "label": "Curated renderer bridge for local, SSH, exposure, WSL, and file operations" + }, + { + "id": "desktop-bootstrap-order", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 142, + "end": 218, + "language": "typescript", + "label": "Endpoint selection, desktop protocol, IPC, primary start, and parallel WSL reconciliation" + }, + { + "id": "desktop-primary-platform-choice", + "path": "apps/desktop/src/backend/DesktopBackendConfiguration.ts", + "start": 689, + "end": 728, + "language": "typescript", + "label": "Host-local primary label with the Windows-only WSL override" + }, + { + "id": "desktop-pool-scope-lifecycle", + "path": "apps/desktop/src/backend/DesktopBackendPool.ts", + "start": 327, + "end": 419, + "language": "typescript", + "label": "Per-instance child scopes and primary-protected unregister lifecycle" + }, + { + "id": "desktop-process-channels", + "path": "apps/desktop/src/backend/DesktopBackendManager.ts", + "start": 451, + "end": 526, + "language": "typescript", + "label": "Bootstrap, telemetry, diagnostics-control, and WSL stdin process channels" + }, + { + "id": "desktop-http-readiness-loop", + "path": "apps/desktop/src/backend/DesktopBackendManager.ts", + "start": 566, + "end": 591, + "language": "typescript", + "label": "Repeated HTTP readiness budgets while the local child remains alive" + }, + { + "id": "desktop-updater-quit-boundary", + "path": "apps/desktop/src/app/DesktopLifecycle.ts", + "start": 198, + "end": 227, + "language": "typescript", + "label": "Updater-controlled quit bypasses the ordinary before-quit hold" + }, + { + "id": "desktop-all-instance-shutdown", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 295, + "end": 315, + "language": "typescript", + "label": "Application finalizer gracefully stops every registered local backend" + }, + { + "id": "distribution-cli-contract", + "path": "apps/server/package.json", + "start": 1, + "end": 22, + "language": "json", + "label": "The t3 npm executable and published dist payload" + }, + { + "id": "distribution-cli-bundles-web", + "path": "apps/server/scripts/cli.ts", + "start": 143, + "end": 176, + "language": "typescript", + "label": "CLI build copies the web renderer into the server package" + }, + { + "id": "distribution-desktop-artifact-contract", + "path": "scripts/build-desktop-artifact.ts", + "start": 2059, + "end": 2107, + "language": "typescript", + "label": "Desktop artifact naming, packed resources, update feed, and macOS target" + }, + { + "id": "distribution-desktop-linux-windows-targets", + "path": "scripts/build-desktop-artifact.ts", + "start": 2133, + "end": 2174, + "language": "typescript", + "label": "Linux and Windows desktop target configuration" + }, + { + "id": "distribution-release-matrix", + "path": ".github/workflows/release.yml", + "start": 342, + "end": 397, + "language": "yaml", + "label": "The four desktop artifacts actually shipped by release CI" + }, + { + "id": "distribution-cli-before-release", + "path": ".github/workflows/release.yml", + "start": 709, + "end": 791, + "language": "yaml", + "label": "Exact CLI publication gates GitHub Release publication" + }, + { + "id": "distribution-mobile-fingerprint-publish", + "path": ".github/workflows/mobile-eas-production.yml", + "start": 263, + "end": 286, + "language": "yaml", + "label": "Production OTA publication requires a matching native fingerprint" + }, + { + "id": "distribution-download-resolution", + "path": "apps/marketing/src/pages/download.astro", + "start": 89, + "end": 132, + "language": "typescript", + "label": "Marketing download links resolve against latest GitHub Release assets" + }, + { + "id": "distribution-aur-selection", + "path": "packaging/aur/scripts/release.sh", + "start": 9, + "end": 44, + "language": "bash", + "label": "Stable and nightly tags select separate checksum-pinned AUR packages" + }, + { + "id": "release-channel-resolution", + "path": ".github/workflows/release.yml", + "start": 103, + "end": 155, + "language": "bash", + "label": "Stable and nightly releases derive different versions, tags, and latest policy" + }, + { + "id": "release-exact-version-invariant", + "path": "docs/operations/release.md", + "start": 174, + "end": 187, + "language": "markdown", + "label": "npm exact-version publication precedes every released client" + }, + { + "id": "desktop-update-check-download", + "path": "apps/desktop/src/updates/DesktopUpdates.ts", + "start": 334, + "end": 458, + "language": "typescript", + "label": "Desktop channel selection, update checks, and user-triggered download" + }, + { + "id": "desktop-update-install-boundary", + "path": "apps/desktop/src/updates/DesktopUpdates.ts", + "start": 465, + "end": 575, + "language": "typescript", + "label": "Desktop install stops every backend before updater-controlled restart" + }, + { + "id": "server-update-exact-preflight", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 64, + "end": 169, + "language": "typescript", + "label": "Server self-update accepts only an exact version that passes staged preflight" + }, + { + "id": "server-update-launcher-handoff", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 171, + "end": 191, + "language": "typescript", + "label": "Prepared server runtime is handed to the stable launcher by update id" + }, + { + "id": "mobile-ota-fingerprint-policy", + "path": "apps/mobile/app.config.ts", + "start": 159, + "end": 180, + "language": "typescript", + "label": "Mobile runtime compatibility is keyed by native fingerprint" + }, + { + "id": "analytics-posthog-controls", + "path": "apps/server/src/telemetry/AnalyticsService.ts", + "start": 31, + "end": 44, + "language": "typescript", + "label": "PostHog destination, opt-out, and bounded buffer configuration" + }, + { + "id": "analytics-posthog-boundary", + "path": "apps/server/src/telemetry/AnalyticsService.ts", + "start": 69, + "end": 134, + "language": "typescript", + "label": "Installation-scoped analytics payload and PostHog batch boundary" + }, + { + "id": "analytics-identity-ladder", + "path": "apps/server/src/telemetry/Identify.ts", + "start": 248, + "end": 299, + "language": "typescript", + "label": "Hashed Codex, Claude, then anonymous analytics identity ladder" + }, + { + "id": "observability-local-remote-lanes", + "path": "apps/server/src/observability/Layers/Observability.ts", + "start": 19, + "end": 93, + "language": "typescript", + "label": "Local trace sink remains active while OTLP traces and metrics are optional" + }, + { + "id": "observability-browser-ingest", + "path": "apps/server/src/http.ts", + "start": 146, + "end": 199, + "language": "typescript", + "label": "Authenticated browser traces land locally before optional OTLP forwarding" + }, + { + "id": "resource-telemetry-demand-history", + "path": "docs/internals/resource-telemetry.md", + "start": 129, + "end": 170, + "language": "markdown", + "label": "Bounded native history and diagnostics-driven telemetry streaming" + }, + { + "id": "connect-oauth-hosted-handoff", + "path": "packages/shared/src/connectAuth.ts", + "start": 19, + "end": 104, + "language": "typescript", + "label": "Hosted OAuth handoff and loopback versus out-of-band callbacks" + }, + { + "id": "connect-oauth-cli-pkce", + "path": "apps/server/src/cloud/CliTokenManager.ts", + "start": 266, + "end": 323, + "language": "typescript", + "label": "CLI PKCE, state validation, and authorization-code exchange" + }, + { + "id": "connect-browser-dpop-key", + "path": "apps/web/src/cloud/dpop.ts", + "start": 24, + "end": 143, + "language": "typescript", + "label": "Browser P-256 DPoP key storage, generation, and thumbprint" + }, + { + "id": "connect-environment-link-handshake", + "path": "apps/web/src/cloud/linkEnvironment.ts", + "start": 402, + "end": 493, + "language": "typescript", + "label": "Client-side relay challenge, environment proof, link, and runtime setup" + }, + { + "id": "connect-relay-linker-provision", + "path": "infra/relay/src/environments/EnvironmentLinker.ts", + "start": 227, + "end": 341, + "language": "typescript", + "label": "Relay challenge verification, replay defense, link, and endpoint provisioning" + }, + { + "id": "connect-managed-tunnel-provision", + "path": "infra/relay/src/environments/ManagedEndpointProvider.ts", + "start": 604, + "end": 855, + "language": "typescript", + "label": "Cloudflare tunnel allocation, ingress, DNS, and connector runtime" + }, + { + "id": "connect-environment-runtime-tunnel", + "path": "apps/server/src/cloud/ManagedEndpointRuntime.ts", + "start": 187, + "end": 287, + "language": "typescript", + "label": "Environment-owned managed tunnel child supervision" + }, + { + "id": "connect-relay-environment-mint", + "path": "infra/relay/src/environments/EnvironmentConnector.ts", + "start": 541, + "end": 670, + "language": "typescript", + "label": "Proof-key-bound relay mint request and environment bootstrap credential" + }, + { + "id": "dpop-validation", + "path": "packages/shared/src/dpop.ts", + "start": 1, + "end": 175, + "language": "typescript", + "label": "DPoP signature, target, token hash, and time validation" + }, + { + "id": "managed-relay-dpop-authorization", + "path": "packages/client-runtime/src/authorization/service.ts", + "start": 180, + "end": 299, + "language": "typescript", + "label": "Managed relay bootstrap becomes a distinct DPoP-bound environment session" + }, + { + "id": "reconnect-environment-registry", + "path": "packages/client-runtime/src/connection/registry.ts", + "start": 156, + "end": 289, + "language": "typescript", + "label": "Environment-scoped runtime registry and lease replacement" + }, + { + "id": "reconnect-scoped-environment-refs", + "path": "packages/contracts/src/environment.ts", + "start": 31, + "end": 130, + "language": "typescript", + "label": "Environment descriptors and scoped project and thread references" + }, + { + "id": "reconnect-supervisor-active-lease", + "path": "packages/client-runtime/src/connection/supervisor.ts", + "start": 490, + "end": 615, + "language": "typescript", + "label": "Active prepared connection and RPC session lease lifecycle" + }, + { + "id": "reconnect-supervisor-generation-loop", + "path": "packages/client-runtime/src/connection/supervisor.ts", + "start": 643, + "end": 755, + "language": "typescript", + "label": "Environment supervisor generation, offline, retry, and backoff loop" + }, + { + "id": "reconnect-shell-authoritative-refresh", + "path": "packages/client-runtime/src/state/shell.ts", + "start": 138, + "end": 254, + "language": "typescript", + "label": "Shell cache, authoritative refresh, cursor, and synchronization boundary" + }, + { + "id": "reconnect-thread-snapshot-epoch", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 212, + "end": 338, + "language": "typescript", + "label": "Thread snapshot replacement and stale history epoch guard" + }, + { + "id": "reconnect-mobile-background-demand", + "path": "apps/mobile/src/connection/background-activity.ts", + "start": 44, + "end": 115, + "language": "typescript", + "label": "Mobile background activity reports and retained environment demand" + }, + { + "id": "reconnect-mobile-background-scopes", + "path": "apps/mobile/src/connection/background-activity-scopes.ts", + "start": 24, + "end": 84, + "language": "typescript", + "label": "Reference-counted environment background scopes" + }, + { + "id": "awareness-relay-signal-filter", + "path": "apps/server/src/relay/AgentAwarenessRelay.ts", + "start": 69, + "end": 133, + "language": "typescript", + "label": "Awareness event filtering and projected-state sanitization" + }, + { + "id": "awareness-relay-projected-publish", + "path": "apps/server/src/relay/AgentAwarenessRelay.ts", + "start": 345, + "end": 426, + "language": "typescript", + "label": "Signed awareness publish and unchanged-state suppression" + }, + { + "id": "awareness-apns-delivery-policy", + "path": "infra/relay/src/agentActivity/ApnsDeliveries.ts", + "start": 143, + "end": 326, + "language": "typescript", + "label": "APNs alert gating and Live Activity delivery cadence" + }, + { + "id": "awareness-mobile-registration-gate", + "path": "apps/mobile/src/features/agent-awareness/remoteRegistration.ts", + "start": 69, + "end": 90, + "language": "typescript", + "label": "Relay-accepted mobile registration and replay repair boundary" + }, + { + "id": "awareness-notification-navigation", + "path": "apps/mobile/src/features/agent-awareness/notificationPayload.ts", + "start": 37, + "end": 105, + "language": "typescript", + "label": "Notification payload normalization, deduplication, and navigation" + }, + { + "id": "reconnect-capability-descriptor", + "path": "packages/contracts/src/environment.ts", + "start": 31, + "end": 92, + "language": "typescript", + "label": "Environment version and optional capability descriptor" + }, + { + "id": "reconnect-version-skew-guidance", + "path": "apps/web/src/versionSkew.ts", + "start": 21, + "end": 130, + "language": "typescript", + "label": "Exact client-server version comparison and update guidance" + }, + { + "id": "reconnect-exact-version-update", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 30, + "end": 190, + "language": "typescript", + "label": "Exact-version staging, preflight, and launcher activation handoff" + } +] diff --git a/sources/references.manifest.json b/sources/references.manifest.json new file mode 100644 index 0000000..c68320b --- /dev/null +++ b/sources/references.manifest.json @@ -0,0 +1,4178 @@ +[ + { + "id": "rpc-group", + "path": "packages/contracts/src/rpc.ts", + "kind": "file", + "label": "complete typed RPC group" + }, + { + "id": "server-composition", + "path": "apps/server/src/server.ts", + "start": 123, + "end": 472, + "kind": "file", + "label": "server layer and route composition" + }, + { + "id": "provider-adapter-contract", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 28, + "end": 134, + "kind": "file", + "label": "provider normalization boundary" + }, + { + "id": "client-connection-directory", + "path": "packages/client-runtime/src/connection", + "kind": "directory", + "label": "shared client connection runtime" + }, + { + "id": "rpc-authorization-scopes", + "path": "apps/server/src/auth/RpcAuthorization.ts", + "start": 18, + "end": 139, + "kind": "file", + "label": "exhaustive RPC method-to-scope map" + }, + { + "id": "decider-command-sequence", + "path": "apps/server/src/orchestration/decider.ts", + "start": 181, + "end": 213, + "kind": "file", + "label": "compound-command planning against an evolved temporary read model" + }, + { + "id": "provider-turn-reactor", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1060, + "end": 1174, + "kind": "file", + "label": "committed turn intent to provider send" + }, + { + "id": "provider-runtime-event-union", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 1139, + "end": 1193, + "kind": "file", + "label": "canonical provider runtime event union" + }, + { + "id": "provider-runtime-ingestion", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1490, + "end": 1874, + "kind": "file", + "label": "runtime lifecycle, buffering, and internal command ingestion" + }, + { + "id": "orchestration-event-catalog", + "path": "packages/contracts/src/orchestration.ts", + "start": 1059, + "end": 1504, + "kind": "file", + "label": "durable orchestration event catalog" + }, + { + "id": "checkpoint-diff-dispatch", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 270, + "end": 316, + "kind": "file", + "label": "checkpoint result re-enters the command engine" + }, + { + "id": "checkpoint-runtime-triggers", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 842, + "end": 937, + "kind": "file", + "label": "provider and domain stream checkpoint triggers" + }, + { + "id": "maintainer-product-constraints", + "path": "AGENTS.md", + "start": 3, + "end": 31, + "kind": "file", + "label": "maintainer product boundaries" + }, + { + "id": "thread-state-runtime", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 534, + "end": 645, + "kind": "file", + "label": "HTTP snapshot followed by resumable event subscription" + }, + { + "id": "turn-normalizer", + "path": "apps/server/src/orchestration/Normalizer.ts", + "start": 46, + "end": 178, + "kind": "file", + "label": "timestamp, workspace, and attachment normalization before dispatch" + }, + { + "id": "existing-turn-decider", + "path": "apps/server/src/orchestration/decider.ts", + "start": 926, + "end": 1036, + "kind": "file", + "label": "atomic event batch for a turn on an existing thread" + }, + { + "id": "bootstrap-command-path", + "path": "apps/server/src/ws.ts", + "start": 1000, + "end": 1053, + "kind": "file", + "label": "multi-step bootstrap and compensating cleanup" + }, + { + "id": "command-receipt-handling", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 142, + "end": 170, + "kind": "file", + "label": "accepted receipt replay and aggregate conflict handling" + }, + { + "id": "runtime-receipt-bus", + "path": "apps/server/src/orchestration/Layers/RuntimeReceiptBus.ts", + "start": 1, + "end": 34, + "kind": "file", + "label": "test receipt bus and production no-op" + }, + { + "id": "event-engine-runtime", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 83, + "end": 96, + "kind": "file", + "label": "in-memory read model, queue, and event PubSub" + }, + { + "id": "ws-thread-subscription", + "path": "apps/server/src/ws.ts", + "start": 1394, + "end": 1521, + "kind": "file", + "label": "attach-before-snapshot thread subscription" + }, + { + "id": "provider-event-routing", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 356, + "end": 409, + "kind": "file", + "label": "adapter runtime events routed through ProviderService" + }, + { + "id": "client-environment-registry", + "path": "packages/client-runtime/src/connection/registry.ts", + "start": 128, + "end": 165, + "kind": "file", + "label": "one client registry supervises several environments" + }, + { + "id": "ephemeral-agent-liveness", + "path": "apps/server/src/orchestration/ThreadBackgroundLiveness.ts", + "start": 1, + "end": 14, + "kind": "file", + "label": "background-agent liveness is intentionally ephemeral" + }, + { + "id": "cli-web-bundle", + "path": "apps/server/scripts/cli.ts", + "start": 143, + "end": 176, + "kind": "file", + "label": "server distribution copies the built web client" + }, + { + "id": "cli-build-dependency", + "path": "apps/server/vite.config.ts", + "start": 26, + "end": 55, + "kind": "file", + "label": "server bundle depends on the web build" + }, + { + "id": "web-runtime-selection", + "path": "apps/web/src/main.tsx", + "start": 21, + "end": 59, + "kind": "file", + "label": "hosted, browser, and Electron web runtime selection" + }, + { + "id": "desktop-app-assembly", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 142, + "end": 291, + "kind": "file", + "label": "Electron app and managed backend assembly" + }, + { + "id": "mobile-app-distribution", + "path": "apps/mobile/app.config.ts", + "start": 159, + "end": 180, + "kind": "file", + "label": "mobile runtime version and distribution configuration" + }, + { + "id": "marketing-site-runtime", + "path": "apps/marketing/package.json", + "start": 1, + "end": 20, + "kind": "file", + "label": "independent Astro marketing package boundary" + }, + { + "id": "desktop-native-boundary", + "path": "apps/desktop/src/preload.ts", + "start": 30, + "end": 185, + "kind": "file", + "label": "curated desktop-native API boundary" + }, + { + "id": "mobile-local-state-cleanup", + "path": "apps/mobile/src/connection/platform.ts", + "start": 212, + "end": 229, + "kind": "file", + "label": "mobile owns durable drafts and outbox cleanup" + }, + { + "id": "connection-target-model", + "path": "packages/client-runtime/src/connection/model.ts", + "start": 9, + "end": 54, + "kind": "file", + "label": "Primary, Bearer, Relay, and SSH target union" + }, + { + "id": "desktop-preview-gate", + "path": "apps/web/src/routes/_chat.tsx", + "start": 111, + "end": 150, + "kind": "file", + "label": "preview is restricted to the desktop runtime" + }, + { + "id": "mobile-notification-capability", + "path": "apps/mobile/src/features/settings/SettingsRouteScreen.logic.ts", + "start": 1, + "end": 8, + "kind": "file", + "label": "remote notification settings are iOS-only" + }, + { + "id": "mobile-offline-outbox", + "path": "apps/mobile/src/state/use-thread-outbox-drain.ts", + "start": 285, + "end": 424, + "kind": "file", + "label": "durable mobile task outbox drain" + }, + { + "id": "environment-descriptor", + "path": "packages/contracts/src/environment.ts", + "start": 31, + "end": 92, + "kind": "file", + "label": "environment capability and version descriptor" + }, + { + "id": "orchestration-entities", + "path": "packages/contracts/src/orchestration.ts", + "start": 235, + "end": 432, + "kind": "file", + "label": "project, thread, message, plan, session, and checkpoint entities" + }, + { + "id": "orchestration-shell-summary", + "path": "packages/contracts/src/orchestration.ts", + "start": 434, + "end": 507, + "kind": "file", + "label": "shell summary with durable and ephemeral thread state" + }, + { + "id": "orchestration-command-catalog", + "path": "packages/contracts/src/orchestration.ts", + "start": 637, + "end": 1057, + "kind": "file", + "label": "external and internal command catalog" + }, + { + "id": "provider-session-vocabulary", + "path": "packages/contracts/src/provider.ts", + "start": 26, + "end": 66, + "kind": "file", + "label": "canonical provider session lifecycle contract" + }, + { + "id": "provider-runtime-vocabulary", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 52, + "end": 197, + "kind": "file", + "label": "canonical provider turn, message, content, and activity vocabulary" + }, + { + "id": "provider-session-binding", + "path": "apps/server/src/persistence/ProviderSessionRuntime.ts", + "start": 147, + "end": 236, + "kind": "file", + "label": "persisted provider binding and continuation cursor" + }, + { + "id": "provider-session-recovery", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 411, + "end": 544, + "kind": "file", + "label": "lazy adapter-session creation and recovery" + }, + { + "id": "startup-provider-reconciliation", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 296, + "end": 377, + "kind": "file", + "label": "orphaned provider-session startup reconciliation" + }, + { + "id": "provider-adapter-capabilities", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 28, + "end": 35, + "kind": "file", + "label": "common adapter capability declaration" + }, + { + "id": "root-workspace-manifest", + "path": "package.json", + "start": 1, + "end": 61, + "kind": "file", + "label": "monorepo scripts, build graph entrypoints, and toolchain" + }, + { + "id": "pnpm-workspace", + "path": "pnpm-workspace.yaml", + "start": 1, + "end": 160, + "kind": "file", + "label": "workspace packages, catalogs, and dependency policy" + }, + { + "id": "contracts-package", + "path": "packages/contracts/package.json", + "start": 1, + "end": 34, + "kind": "file", + "label": "shared contract package boundaries" + }, + { + "id": "client-runtime-package", + "path": "packages/client-runtime/package.json", + "start": 1, + "end": 172, + "kind": "file", + "label": "shared client runtime package boundary" + }, + { + "id": "desktop-package", + "path": "apps/desktop/package.json", + "start": 1, + "end": 39, + "kind": "file", + "label": "Electron package and native dependencies" + }, + { + "id": "mobile-package", + "path": "apps/mobile/package.json", + "start": 1, + "end": 147, + "kind": "file", + "label": "React Native/Expo package and independent version domain" + }, + { + "id": "resource-monitor-crate", + "path": "native/resource-monitor/Cargo.toml", + "start": 1, + "end": 17, + "kind": "file", + "label": "native resource-monitor crate" + }, + { + "id": "cli-package-surface", + "path": "apps/server/package.json", + "start": 1, + "end": 52, + "kind": "file", + "label": "published t3 package, executable, files, and runtime constraints" + }, + { + "id": "cli-root-dispatch", + "path": "apps/server/src/bin.ts", + "start": 23, + "end": 71, + "kind": "file", + "label": "root command, cloud gate, and subcommand dispatch" + }, + { + "id": "cli-service-preflight-command", + "path": "apps/server/src/cli/servicePreflight.ts", + "start": 7, + "end": 16, + "kind": "file", + "label": "hidden internal service preflight command" + }, + { + "id": "cli-command-semantics", + "path": "apps/server/src/cli/server.ts", + "start": 8, + "end": 35, + "kind": "file", + "label": "start and headless serve handoff" + }, + { + "id": "cli-config-channels", + "path": "apps/server/src/cli/config.ts", + "start": 20, + "end": 191, + "kind": "file", + "label": "CLI flags and environment configuration channels" + }, + { + "id": "cli-config-resolver", + "path": "apps/server/src/cli/config.ts", + "start": 210, + "end": 392, + "kind": "file", + "label": "resolved server configuration precedence and defaults" + }, + { + "id": "available-port-selection", + "path": "packages/shared/src/Net.ts", + "start": 194, + "end": 200, + "kind": "file", + "label": "preferred port followed by OS-assigned ephemeral fallback" + }, + { + "id": "desktop-backend-port-selection", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 69, + "end": 103, + "kind": "file", + "label": "desktop parent sequential port selection helper" + }, + { + "id": "desktop-bootstrap-envelope", + "path": "apps/desktop/src/backend/DesktopBackendConfiguration.ts", + "start": 366, + "end": 414, + "kind": "file", + "label": "desktop parent bootstrap port and process metadata envelope" + }, + { + "id": "server-path-layout", + "path": "apps/server/src/config.ts", + "start": 99, + "end": 155, + "kind": "file", + "label": "development and userdata path derivation" + }, + { + "id": "static-dir-resolution", + "path": "apps/server/src/config.ts", + "start": 206, + "end": 225, + "kind": "file", + "label": "bundled and monorepo static-client lookup" + }, + { + "id": "cli-bundle-policy", + "path": "apps/server/vite.config.ts", + "start": 8, + "end": 75, + "kind": "file", + "label": "CLI bundling policy, native external boundary, and build metadata" + }, + { + "id": "cli-publish-assertions", + "path": "apps/server/scripts/cli.ts", + "start": 225, + "end": 304, + "kind": "file", + "label": "publish-time client and launcher artifact assertions" + }, + { + "id": "cli-native-dependency-boundary", + "path": "scripts/lib/cli-external-packages.ts", + "start": 1, + "end": 102, + "kind": "file", + "label": "native packages kept outside the bundled executable" + }, + { + "id": "service-launcher-trial-handoff", + "path": "apps/server/src/serviceLauncher.ts", + "start": 353, + "end": 600, + "kind": "file", + "label": "managed service update trial, handoff, commit, and rollback" + }, + { + "id": "static-and-dev-serving", + "path": "apps/server/src/http.ts", + "start": 233, + "end": 322, + "kind": "file", + "label": "development redirect, static fallback, and missing-client response" + }, + { + "id": "startup-browser-target", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 257, + "end": 288, + "kind": "file", + "label": "startup browser and pairing target resolution" + }, + { + "id": "startup-headless-access", + "path": "apps/server/src/startupAccess.ts", + "start": 71, + "end": 147, + "kind": "file", + "label": "actual listening address and fragment-based headless pairing output" + }, + { + "id": "server-platform-layers", + "path": "apps/server/src/server.ts", + "start": 123, + "end": 240, + "kind": "file", + "label": "Bun or Node platform and HTTP server layer selection" + }, + { + "id": "server-service-composition", + "path": "apps/server/src/server.ts", + "start": 242, + "end": 429, + "kind": "file", + "label": "server persistence, runtime, provider, workspace, and operational layer composition" + }, + { + "id": "server-route-readiness-barrier", + "path": "apps/server/src/server.ts", + "start": 431, + "end": 437, + "kind": "file", + "label": "global route-execution readiness barrier" + }, + { + "id": "server-route-composition", + "path": "apps/server/src/server.ts", + "start": 447, + "end": 472, + "kind": "file", + "label": "HTTP API, assets, WebSocket RPC, and MCP route composition" + }, + { + "id": "server-activation-barrier", + "path": "apps/server/src/server.ts", + "start": 474, + "end": 689, + "kind": "file", + "label": "prepared roots, activation, routes, and scoped server ownership" + }, + { + "id": "startup-command-gate", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 94, + "end": 136, + "kind": "file", + "label": "command readiness deferred and failure propagation" + }, + { + "id": "startup-authoritative-sequence", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 385, + "end": 583, + "kind": "file", + "label": "authoritative startup ordering and failure path" + }, + { + "id": "activation-fork-parked", + "path": "apps/server/src/serverActivation.ts", + "start": 11, + "end": 25, + "kind": "file", + "label": "parked child fiber activation semantics" + }, + { + "id": "sqlite-acquisition", + "path": "apps/server/src/persistence/Layers/Sqlite.ts", + "start": 19, + "end": 41, + "kind": "file", + "label": "SQLite pragmas and migration acquisition" + }, + { + "id": "sqlite-migration-manifest", + "path": "apps/server/src/persistence/Migrations.ts", + "start": 15, + "end": 152, + "kind": "file", + "label": "ordered static SQLite migration manifest" + }, + { + "id": "orchestration-reactor-start", + "path": "apps/server/src/orchestration/Layers/OrchestrationReactor.ts", + "start": 14, + "end": 31, + "kind": "file", + "label": "production orchestration reactor startup surface" + }, + { + "id": "drainable-worker-semantics", + "path": "packages/shared/src/DrainableWorker.ts", + "start": 1, + "end": 70, + "kind": "file", + "label": "serialized worker drain semantics and test synchronization intent" + }, + { + "id": "stale-startup-overview", + "path": "docs/internals/overview.md", + "start": 124, + "end": 130, + "kind": "file", + "label": "stale documented startup sequence" + }, + { + "id": "orchestration-snapshot-contracts", + "path": "packages/contracts/src/orchestration.ts", + "start": 501, + "end": 635, + "kind": "file", + "label": "shell and thread snapshots, cursors, and pagination contracts" + }, + { + "id": "orchestration-thread-stream-contract", + "path": "packages/contracts/src/orchestration.ts", + "start": 1506, + "end": 1519, + "kind": "file", + "label": "thread snapshot, event, and synchronized stream union" + }, + { + "id": "orchestration-rpc-schema-map", + "path": "packages/contracts/src/orchestration.ts", + "start": 1680, + "end": 1713, + "kind": "file", + "label": "orchestration RPC input and output schema map" + }, + { + "id": "rpc-orchestration-definitions", + "path": "packages/contracts/src/rpc.ts", + "start": 885, + "end": 948, + "kind": "file", + "label": "typed orchestration unary and streaming RPC definitions" + }, + { + "id": "environment-http-contracts", + "path": "packages/contracts/src/environmentHttp.ts", + "start": 486, + "end": 531, + "kind": "file", + "label": "typed environment HTTP orchestration contracts" + }, + { + "id": "orchestration-http-snapshots", + "path": "apps/server/src/orchestration/http.ts", + "start": 22, + "end": 108, + "kind": "file", + "label": "HTTP shell and thread snapshot implementations" + }, + { + "id": "ws-authenticated-session", + "path": "apps/server/src/ws.ts", + "start": 385, + "end": 538, + "kind": "file", + "label": "authenticated WebSocket session and per-method authorization wrapper" + }, + { + "id": "ws-shell-coalescing", + "path": "apps/server/src/ws.ts", + "start": 644, + "end": 819, + "kind": "file", + "label": "shell invalidation coalescing and refetch behavior" + }, + { + "id": "ws-advertised-capabilities", + "path": "apps/server/src/ws.ts", + "start": 1077, + "end": 1116, + "kind": "file", + "label": "server configuration and synchronization capability advertisement" + }, + { + "id": "ws-dispatch-handler", + "path": "apps/server/src/ws.ts", + "start": 1124, + "end": 1221, + "kind": "file", + "label": "authorized command normalization and dispatch handler" + }, + { + "id": "ws-shell-resume", + "path": "apps/server/src/ws.ts", + "start": 1270, + "end": 1375, + "kind": "file", + "label": "bounded shell replay and snapshot fallback" + }, + { + "id": "ws-resume-gap-cap", + "path": "apps/server/src/ws.ts", + "start": 308, + "end": 315, + "kind": "file", + "label": "one-thousand-event shell and thread resume gap limits" + }, + { + "id": "ws-command-entry-policy", + "path": "apps/server/src/ws.ts", + "start": 821, + "end": 1074, + "kind": "file", + "label": "WebSocket bootstrap compensation and startup command queue" + }, + { + "id": "command-commit-acknowledgement", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 197, + "end": 260, + "kind": "file", + "label": "transactional event commit before sequence acknowledgement" + }, + { + "id": "ws-route-json-protocol", + "path": "apps/server/src/ws.ts", + "start": 2398, + "end": 2468, + "kind": "file", + "label": "WebSocket upgrade, authenticated RPC handler, and JSON serialization layer" + }, + { + "id": "client-rpc-session", + "path": "packages/client-runtime/src/rpc/session.ts", + "start": 68, + "end": 145, + "kind": "file", + "label": "one WebSocket RPC attempt with internal retries disabled" + }, + { + "id": "client-rpc-subscriptions", + "path": "packages/client-runtime/src/rpc/client.ts", + "start": 178, + "end": 280, + "kind": "file", + "label": "session-aware dynamic subscription replacement" + }, + { + "id": "client-shell-convergence", + "path": "packages/client-runtime/src/state/shellReducer.ts", + "start": 1, + "end": 45, + "kind": "file", + "label": "shell sequence watermark and overlapping event de-duplication" + }, + { + "id": "client-thread-convergence", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 316, + "end": 365, + "kind": "file", + "label": "thread snapshot replacement and sequence de-duplication" + }, + { + "id": "auth-contracts", + "path": "packages/contracts/src/auth.ts", + "start": 29, + "end": 202, + "kind": "file", + "label": "authentication policy, session, method, and scope contracts" + }, + { + "id": "auth-policy-derivation", + "path": "apps/server/src/auth/EnvironmentAuthPolicy.ts", + "start": 16, + "end": 47, + "kind": "file", + "label": "runtime mode and bind-host authentication policy derivation" + }, + { + "id": "auth-session-exchange", + "path": "apps/server/src/auth/EnvironmentAuth.ts", + "start": 655, + "end": 744, + "kind": "file", + "label": "browser and token session exchange with scope subset checks" + }, + { + "id": "auth-request-precedence", + "path": "apps/server/src/auth/EnvironmentAuth.ts", + "start": 592, + "end": 632, + "kind": "file", + "label": "cookie, Bearer, and DPoP request credential precedence" + }, + { + "id": "auth-pairing-ticket-upgrade", + "path": "apps/server/src/auth/EnvironmentAuth.ts", + "start": 769, + "end": 961, + "kind": "file", + "label": "pairing issue, WebSocket ticket, and upgrade authentication" + }, + { + "id": "pairing-grant-ttls", + "path": "apps/server/src/auth/PairingGrantStore.ts", + "start": 241, + "end": 330, + "kind": "file", + "label": "standard, startup, and desktop bootstrap grant lifetimes" + }, + { + "id": "pairing-grant-consumption", + "path": "apps/server/src/auth/PairingGrantStore.ts", + "start": 379, + "end": 568, + "kind": "file", + "label": "pairing grant issuance and one-use consumption" + }, + { + "id": "pairing-sqlite-consumption", + "path": "apps/server/src/persistence/AuthPairingLinks.ts", + "start": 125, + "end": 180, + "kind": "file", + "label": "atomic SQLite pairing-link consumption" + }, + { + "id": "session-default-ttls", + "path": "apps/server/src/auth/SessionStore.ts", + "start": 410, + "end": 434, + "kind": "file", + "label": "normal session and WebSocket ticket default lifetimes" + }, + { + "id": "session-issue-verification", + "path": "apps/server/src/auth/SessionStore.ts", + "start": 603, + "end": 747, + "kind": "file", + "label": "signed session issue and SQLite-backed verification" + }, + { + "id": "websocket-ticket-session", + "path": "apps/server/src/auth/SessionStore.ts", + "start": 749, + "end": 851, + "kind": "file", + "label": "WebSocket ticket issue and current session reload" + }, + { + "id": "session-revocation", + "path": "apps/server/src/auth/SessionStore.ts", + "start": 876, + "end": 929, + "kind": "file", + "label": "session revocation persistence and access events" + }, + { + "id": "auth-http-exchange", + "path": "apps/server/src/auth/http.ts", + "start": 164, + "end": 319, + "kind": "file", + "label": "HTTP credential exchange and cookie behavior" + }, + { + "id": "auth-delegated-scopes", + "path": "apps/server/src/auth/http.ts", + "start": 335, + "end": 432, + "kind": "file", + "label": "pairing delegation and client-session scope enforcement" + }, + { + "id": "server-secret-store", + "path": "apps/server/src/auth/ServerSecretStore.ts", + "start": 152, + "end": 310, + "kind": "file", + "label": "secret file permissions and atomic persistence" + }, + { + "id": "dpop-replay-record", + "path": "apps/server/src/auth/dpop.ts", + "start": 29, + "end": 87, + "kind": "file", + "label": "durable exclusive DPoP replay marker" + }, + { + "id": "startup-pairing-fragment", + "path": "apps/server/src/startupAccess.ts", + "start": 92, + "end": 97, + "kind": "file", + "label": "pairing token encoded in the URL fragment" + }, + { + "id": "client-pairing-fragment-strip", + "path": "apps/web/src/environments/primary/auth.ts", + "start": 156, + "end": 176, + "kind": "file", + "label": "browser pairing fragment extraction and immediate removal" + }, + { + "id": "hosted-static-auth-boundary", + "path": "apps/web/src/routes/__root.tsx", + "start": 61, + "end": 129, + "kind": "file", + "label": "hosted static and hosted pairing routes bypass the primary-server auth gate" + }, + { + "id": "hosted-pairing-url", + "path": "apps/web/src/hostedPairing.ts", + "start": 47, + "end": 80, + "kind": "file", + "label": "hosted pairing backend query and credential fragment" + }, + { + "id": "hosted-pairing-registration", + "path": "apps/web/src/components/auth/PairingRouteSurface.tsx", + "start": 166, + "end": 231, + "kind": "file", + "label": "hosted pairing fragment removal and remote-environment registration" + }, + { + "id": "hosted-bearer-onboarding", + "path": "packages/client-runtime/src/connection/onboarding.ts", + "start": 86, + "end": 118, + "kind": "file", + "label": "direct hosted pairing exchanges a grant for a Bearer environment registration" + }, + { + "id": "hosted-clerk-provider", + "path": "apps/web/src/main.tsx", + "start": 31, + "end": 59, + "kind": "file", + "label": "Clerk and managed-relay auth wrap the configured cloud client" + }, + { + "id": "managed-relay-auth-provider", + "path": "apps/web/src/cloud/managedAuth.tsx", + "start": 39, + "end": 115, + "kind": "file", + "label": "Clerk account state activates the managed-relay session" + }, + { + "id": "auth-session-row-shape", + "path": "apps/server/src/persistence/AuthSessions.ts", + "start": 34, + "end": 55, + "kind": "file", + "label": "SQLite session row fields exclude the DPoP key thumbprint" + }, + { + "id": "auth-doc-ticket-overclaim", + "path": "docs/internals/environment-auth.md", + "start": 95, + "end": 111, + "kind": "file", + "label": "documentation claim that WebSocket tickets carry scopes" + }, + { + "id": "decider-effect-dependencies", + "path": "apps/server/src/orchestration/decider.ts", + "start": 18, + "end": 173, + "kind": "file", + "label": "clock, UUID, and event-envelope dependencies in decision logic" + }, + { + "id": "bootstrap-saga-full", + "path": "apps/server/src/ws.ts", + "start": 821, + "end": 1053, + "kind": "file", + "label": "WebSocket-only thread bootstrap and compensating delete saga" + }, + { + "id": "event-envelope-fields", + "path": "packages/contracts/src/orchestration.ts", + "start": 1323, + "end": 1355, + "kind": "file", + "label": "public durable event envelope" + }, + { + "id": "event-store-versioning", + "path": "apps/server/src/persistence/Layers/OrchestrationEventStore.ts", + "start": 70, + "end": 157, + "kind": "file", + "label": "actor classification, global sequence, and internal stream version assignment" + }, + { + "id": "engine-rejected-receipt", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 287, + "end": 325, + "kind": "file", + "label": "best-effort persistence of invariant rejection receipts" + }, + { + "id": "engine-failure-reconciliation", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 109, + "end": 130, + "kind": "file", + "label": "same-process durable-tail reconciliation after dispatch failure" + }, + { + "id": "engine-receipt-publication-boundary", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 142, + "end": 259, + "kind": "file", + "label": "receipt short-circuit, atomic commit, and post-commit publication" + }, + { + "id": "projection-registration-order", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1609, + "end": 1646, + "kind": "file", + "label": "nine projectors in synchronous application order" + }, + { + "id": "projection-bootstrap-cursors", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1681, + "end": 1727, + "kind": "file", + "label": "sequential projector catch-up from independent cursors" + }, + { + "id": "projection-read-cap", + "path": "apps/server/src/persistence/Layers/OrchestrationEventStore.ts", + "start": 67, + "end": 267, + "kind": "file", + "label": "default one-thousand-event total read limit and pagination loop" + }, + { + "id": "thread-detail-turn-limit", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 2669, + "end": 2700, + "kind": "file", + "label": "thread detail bounds pathological fan-out at 150 raw turns per page" + }, + { + "id": "checkpoint-projector-noop", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1477, + "end": 1487, + "kind": "file", + "label": "named checkpoint projector currently performs no writes" + }, + { + "id": "turn-checkpoint-projection", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1404, + "end": 1448, + "kind": "file", + "label": "checkpoint completion fields are written into projected turn rows" + }, + { + "id": "projection-snapshot-shapes", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 1738, + "end": 1940, + "kind": "file", + "label": "optimized command model excludes message, activity, and checkpoint collections" + }, + { + "id": "projection-attachment-cleanup", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 330, + "end": 468, + "kind": "file", + "label": "projected attachment reference collection and filesystem cleanup" + }, + { + "id": "reactor-composite-start", + "path": "apps/server/src/orchestration/Layers/OrchestrationReactor.ts", + "start": 14, + "end": 31, + "kind": "file", + "label": "independent orchestration reactor roots" + }, + { + "id": "provider-reactor-hot-subscription", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1377, + "end": 1439, + "kind": "file", + "label": "hot stream subscription, worker wiring, and partial drain surface" + }, + { + "id": "provider-turn-dedupe-cache", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 89, + "end": 325, + "kind": "file", + "label": "bounded volatile turn-start duplicate suppression cache" + }, + { + "id": "provider-send-binding-order", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 771, + "end": 801, + "kind": "file", + "label": "adapter send precedes local running-binding persistence" + }, + { + "id": "provider-runtime-publish", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 286, + "end": 295, + "kind": "file", + "label": "best-effort runtime log write before hot PubSub publication" + }, + { + "id": "runtime-ingestion-buffer-dispatch", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 884, + "end": 1162, + "kind": "file", + "label": "randomized internal command IDs and buffer invalidation before dispatch" + }, + { + "id": "runtime-ingestion-worker", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 2040, + "end": 2082, + "kind": "file", + "label": "hot runtime and no-op domain inputs feed one failure-isolating worker" + }, + { + "id": "drainable-worker-close", + "path": "packages/shared/src/DrainableWorker.ts", + "start": 31, + "end": 69, + "kind": "file", + "label": "serialized queue, test drain, and interrupting scope finalizer" + }, + { + "id": "startup-parked-reactors", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 385, + "end": 535, + "kind": "file", + "label": "parked reactor roots, pre-activation reconciliation, and command-ready gate" + }, + { + "id": "agent-awareness-recovery", + "path": "apps/server/src/relay/AgentAwarenessRelay.ts", + "start": 337, + "end": 631, + "kind": "file", + "label": "volatile confirmation state and delayed active-thread snapshot publication" + }, + { + "id": "migration-runner", + "path": "apps/server/src/persistence/Migrations.ts", + "start": 15, + "end": 152, + "kind": "file", + "label": "static migration manifest and automatically tracked runner" + }, + { + "id": "checkpoint-diff-blob-migration", + "path": "apps/server/src/persistence/Migrations/003_CheckpointDiffBlobs.ts", + "start": 1, + "end": 22, + "kind": "file", + "label": "checkpoint diff blob table and index migration" + }, + { + "id": "service-update-recovery", + "path": "apps/server/src/serviceLauncher.ts", + "start": 73, + "end": 600, + "kind": "file", + "label": "durable update state, SQLite backup, restore marker, trial, and rollback" + }, + { + "id": "settings-secret-order", + "path": "apps/server/src/serverSettings.ts", + "start": 427, + "end": 642, + "kind": "file", + "label": "secret mutations precede settings JSON, cache, and publication" + }, + { + "id": "settings-load-fallbacks", + "path": "apps/server/src/serverSettings.ts", + "start": 302, + "end": 408, + "kind": "file", + "label": "missing and malformed settings fallbacks plus secret materialization" + }, + { + "id": "settings-atomic-write", + "path": "apps/server/src/atomicWrite.ts", + "start": 5, + "end": 24, + "kind": "file", + "label": "same-directory temporary settings write and rename" + }, + { + "id": "secret-store-atomic-boundary", + "path": "apps/server/src/auth/ServerSecretStore.ts", + "start": 187, + "end": 302, + "kind": "file", + "label": "secret temp-file rename, exclusive creation, and removal semantics" + }, + { + "id": "attachment-projection-cleanup", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1648, + "end": 1678, + "kind": "file", + "label": "projector SQL and cursor step precede best-effort attachment cleanup" + }, + { + "id": "attachment-path-safety", + "path": "apps/server/src/attachmentPaths.ts", + "start": 4, + "end": 27, + "kind": "file", + "label": "attachment path normalization and root-containment check" + }, + { + "id": "terminal-history-persistence", + "path": "apps/server/src/terminal/Manager.ts", + "start": 1355, + "end": 1496, + "kind": "file", + "label": "coalesced direct-overwrite terminal history persistence and restore" + }, + { + "id": "terminal-history-defaults", + "path": "apps/server/src/terminal/Manager.ts", + "start": 77, + "end": 84, + "kind": "file", + "label": "terminal history cap and persistence debounce defaults" + }, + { + "id": "terminal-output-persistence-order", + "path": "apps/server/src/terminal/Manager.ts", + "start": 1630, + "end": 1726, + "kind": "file", + "label": "terminal output updates memory, queues persistence, then publishes" + }, + { + "id": "terminal-explicit-close", + "path": "apps/server/src/terminal/Manager.ts", + "start": 1963, + "end": 2000, + "kind": "file", + "label": "explicit terminal close persists and drains one history key" + }, + { + "id": "terminal-scope-finalizer", + "path": "apps/server/src/terminal/Manager.ts", + "start": 2116, + "end": 2160, + "kind": "file", + "label": "manager finalizer kills sessions without a global history drain" + }, + { + "id": "terminal-lazy-history-open", + "path": "apps/server/src/terminal/Manager.ts", + "start": 2145, + "end": 2203, + "kind": "file", + "label": "first open loads saved text before starting a new terminal process" + }, + { + "id": "provider-event-log-contract", + "path": "apps/server/src/provider/Layers/EventNdjsonLogger.ts", + "start": 1, + "end": 49, + "kind": "file", + "label": "best-effort provider log defaults and omitted transient events" + }, + { + "id": "provider-event-log-drain", + "path": "apps/server/src/provider/Layers/EventNdjsonLogger.ts", + "start": 340, + "end": 615, + "kind": "file", + "label": "provider log buffer drain, retention failures, and no-op setup fallback" + }, + { + "id": "observability-runtime", + "path": "apps/server/src/observability/Layers/Observability.ts", + "start": 19, + "end": 93, + "kind": "file", + "label": "local trace sink with optional OTLP trace and metrics delegates" + }, + { + "id": "server-logger-sinks", + "path": "apps/server/src/serverLogger.ts", + "start": 8, + "end": 16, + "kind": "file", + "label": "pretty console and tracer logger composition" + }, + { + "id": "checkpoint-git-capture-restore", + "path": "apps/server/src/vcs/GitVcsDriver.ts", + "start": 708, + "end": 828, + "kind": "file", + "label": "hidden-ref capture and content restore with index reset" + }, + { + "id": "checkpoint-revert-saga", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 690, + "end": 818, + "kind": "file", + "label": "Git restore, provider rollback, ref cleanup, and durable completion ordering" + }, + { + "id": "checkpoint-capture-dispatch-order", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 221, + "end": 351, + "kind": "file", + "label": "hidden-ref capture and diff precede durable checkpoint metadata dispatch" + }, + { + "id": "projection-tombstones", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 490, + "end": 857, + "kind": "file", + "label": "project and thread deletion update projection tombstones" + }, + { + "id": "revert-derived-pruning", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 948, + "end": 1475, + "kind": "file", + "label": "thread revert prunes and rebuilds selected derived projection rows" + }, + { + "id": "event-store-api-surface", + "path": "apps/server/src/persistence/Services/OrchestrationEventStore.ts", + "start": 22, + "end": 55, + "kind": "file", + "label": "event store append and ordered read API surface" + }, + { + "id": "receipt-repository-api-surface", + "path": "apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts", + "start": 25, + "end": 63, + "kind": "file", + "label": "command receipt schema plus upsert and lookup API surface" + }, + { + "id": "provider-binding-delete-surface", + "path": "apps/server/src/persistence/ProviderSessionRuntime.ts", + "start": 70, + "end": 103, + "kind": "file", + "label": "provider runtime repository includes an explicit delete operation" + }, + { + "id": "thread-deletion-side-effects", + "path": "apps/server/src/orchestration/Layers/ThreadDeletionReactor.ts", + "start": 40, + "end": 97, + "kind": "file", + "label": "hot post-delete provider and terminal cleanup" + }, + { + "id": "provider-session-contract", + "path": "packages/contracts/src/provider.ts", + "start": 34, + "end": 86, + "kind": "file", + "label": "canonical provider session identity and runtime state" + }, + { + "id": "provider-session-directory", + "path": "apps/server/src/provider/Layers/ProviderSessionDirectory.ts", + "start": 60, + "end": 148, + "kind": "file", + "label": "live provider session directory registration and lookup" + }, + { + "id": "provider-service-session-recovery", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 411, + "end": 544, + "kind": "file", + "label": "binding-led provider session recovery and adoption" + }, + { + "id": "provider-adapter-error-taxonomy", + "path": "apps/server/src/provider/Errors.ts", + "start": 5, + "end": 203, + "kind": "file", + "label": "typed provider boundary and recovery error taxonomy" + }, + { + "id": "provider-runtime-event-base", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 148, + "end": 265, + "kind": "file", + "label": "canonical runtime event identity and base fields" + }, + { + "id": "provider-service-runtime-correlation", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 195, + "end": 409, + "kind": "file", + "label": "provider-instance correlation, optional event logging, and hot publication" + }, + { + "id": "provider-command-control-forwarding", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1176, + "end": 1316, + "kind": "file", + "label": "interrupt, approval, input, stop, and rollback forwarding" + }, + { + "id": "codex-adapter-capabilities", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1984, + "end": 2000, + "kind": "file", + "label": "Codex adapter capability declaration" + }, + { + "id": "claude-adapter-capabilities", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4577, + "end": 4596, + "kind": "file", + "label": "Claude adapter capability declaration and shutdown" + }, + { + "id": "cursor-adapter-capabilities", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 1165, + "end": 1186, + "kind": "file", + "label": "Cursor adapter capability declaration and shutdown" + }, + { + "id": "grok-adapter-capabilities", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 1455, + "end": 1467, + "kind": "file", + "label": "Grok adapter capability declaration" + }, + { + "id": "opencode-adapter-capabilities", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1718, + "end": 1737, + "kind": "file", + "label": "OpenCode adapter capability declaration and shutdown" + }, + { + "id": "opencode-steer-behavior", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.test.ts", + "start": 733, + "end": 810, + "kind": "file", + "label": "OpenCode active-turn steering behavior tests" + }, + { + "id": "provider-runtime-schema-tests", + "path": "packages/contracts/src/providerRuntime.test.ts", + "kind": "file", + "label": "canonical provider runtime schema compatibility tests" + }, + { + "id": "provider-service-routing-tests", + "path": "apps/server/src/provider/Layers/ProviderService.test.ts", + "kind": "file", + "label": "provider routing, binding, recovery, and event-correlation tests" + }, + { + "id": "server-provider-routing-identity", + "path": "packages/contracts/src/server.ts", + "start": 161, + "end": 198, + "kind": "file", + "label": "server provider snapshot with stable instance routing identity" + }, + { + "id": "built-in-provider-drivers", + "path": "apps/server/src/provider/builtInDrivers.ts", + "start": 42, + "end": 53, + "kind": "file", + "label": "five shipped provider driver registrations" + }, + { + "id": "provider-instance-settings-contract", + "path": "packages/contracts/src/settings.ts", + "start": 664, + "end": 733, + "kind": "file", + "label": "explicit provider instance settings and legacy provider fields" + }, + { + "id": "provider-instance-hydration", + "path": "apps/server/src/provider/Layers/ProviderInstanceRegistryHydration.ts", + "start": 65, + "end": 134, + "kind": "file", + "label": "explicit instance map precedence and legacy default hydration" + }, + { + "id": "provider-instance-enabled-precedence", + "path": "apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts", + "start": 97, + "end": 111, + "kind": "file", + "label": "provider instance enabled-state precedence" + }, + { + "id": "provider-instance-build-shadow", + "path": "apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts", + "start": 118, + "end": 214, + "kind": "file", + "label": "scoped instance construction and unavailable shadow fallback" + }, + { + "id": "provider-instance-registry-reconcile", + "path": "apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts", + "start": 228, + "end": 320, + "kind": "file", + "label": "live registry remove, retain, replace, and publication sequence" + }, + { + "id": "provider-unavailable-shadow", + "path": "apps/server/src/provider/unavailableProviderSnapshot.ts", + "start": 45, + "end": 78, + "kind": "file", + "label": "diagnostic snapshot for unavailable provider instances" + }, + { + "id": "provider-adapter-registry-live", + "path": "apps/server/src/provider/Layers/ProviderAdapterRegistry.ts", + "start": 36, + "end": 100, + "kind": "file", + "label": "live adapter facade excludes unavailable instances" + }, + { + "id": "provider-registry-boot-cache", + "path": "apps/server/src/provider/Layers/ProviderRegistry.ts", + "start": 209, + "end": 331, + "kind": "file", + "label": "provider discovery aggregation and boot cache" + }, + { + "id": "provider-registry-live-sync", + "path": "apps/server/src/provider/Layers/ProviderRegistry.ts", + "start": 511, + "end": 693, + "kind": "file", + "label": "per-instance snapshot refresh and live registry synchronization" + }, + { + "id": "provider-managed-snapshot-lifecycle", + "path": "apps/server/src/provider/makeManagedServerProvider.ts", + "start": 27, + "end": 228, + "kind": "file", + "label": "serialized provider discovery and streaming snapshot lifecycle" + }, + { + "id": "provider-instance-environment-contract", + "path": "packages/contracts/src/providerInstance.ts", + "start": 97, + "end": 139, + "kind": "file", + "label": "plain and secret-backed provider environment value contract" + }, + { + "id": "provider-instance-secret-materialization", + "path": "apps/server/src/serverSettings.ts", + "start": 365, + "end": 525, + "kind": "file", + "label": "provider instance secret persistence and materialization" + }, + { + "id": "provider-instance-settings-redaction", + "path": "apps/server/src/serverSettings.ts", + "start": 620, + "end": 650, + "kind": "file", + "label": "provider instance environment re-redaction for clients" + }, + { + "id": "provider-instance-environment-overlay", + "path": "apps/server/src/provider/ProviderInstanceEnvironment.ts", + "start": 1, + "end": 16, + "kind": "file", + "label": "instance environment overlay including blank overrides" + }, + { + "id": "opencode-password-settings", + "path": "packages/contracts/src/settings.ts", + "start": 500, + "end": 521, + "kind": "file", + "label": "OpenCode external server password setting" + }, + { + "id": "opencode-password-persistence-test", + "path": "apps/server/src/serverSettings.test.ts", + "start": 636, + "end": 687, + "kind": "file", + "label": "OpenCode password plaintext persistence regression test" + }, + { + "id": "opencode-external-basic-auth", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1204, + "end": 1233, + "kind": "file", + "label": "external OpenCode endpoint Basic authentication wiring" + }, + { + "id": "opencode-process-ownership", + "path": "apps/server/src/provider/opencodeRuntime.ts", + "start": 477, + "end": 666, + "kind": "file", + "label": "local OpenCode process acquisition, health, and scope-owned release" + }, + { + "id": "provider-service-start-session", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 581, + "end": 813, + "kind": "file", + "label": "instance-routed provider session start and turn send" + }, + { + "id": "provider-reactor-session-continuity", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 469, + "end": 782, + "kind": "file", + "label": "continuation compatibility, restart, and model selection decisions" + }, + { + "id": "codex-continuation-identity", + "path": "apps/server/src/provider/Drivers/CodexDriver.ts", + "start": 122, + "end": 146, + "kind": "file", + "label": "Codex continuation compatibility identity" + }, + { + "id": "claude-continuation-identity", + "path": "apps/server/src/provider/Drivers/ClaudeDriver.ts", + "start": 128, + "end": 165, + "kind": "file", + "label": "Claude continuation compatibility identity" + }, + { + "id": "provider-instance-registry-tests", + "path": "apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts", + "start": 152, + "end": 290, + "kind": "file", + "label": "live provider instance registry replacement tests" + }, + { + "id": "provider-settings-secret-tests", + "path": "apps/server/src/serverSettings.test.ts", + "start": 691, + "end": 752, + "kind": "file", + "label": "provider environment secret persistence and redaction tests" + }, + { + "id": "codex-app-server-child-process", + "path": "packages/effect-codex-app-server/src/client.ts", + "start": 212, + "end": 268, + "kind": "file", + "label": "Codex app-server child process and stdio client construction" + }, + { + "id": "codex-app-server-protocol-lifecycle", + "path": "packages/effect-codex-app-server/src/protocol.ts", + "start": 154, + "end": 342, + "kind": "file", + "label": "pending JSON-RPC requests, notifications, and transport termination" + }, + { + "id": "codex-app-server-errors", + "path": "packages/effect-codex-app-server/src/errors.ts", + "start": 119, + "end": 409, + "kind": "file", + "label": "typed Codex app-server transport and protocol errors" + }, + { + "id": "codex-adapter-event-consumer", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1694, + "end": 1764, + "kind": "file", + "label": "session-scoped Codex event consumer started before adapter return" + }, + { + "id": "codex-adapter-error-mapping", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1508, + "end": 1566, + "kind": "file", + "label": "Codex native error and stderr classification" + }, + { + "id": "codex-adapter-model-reroute", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1321, + "end": 1328, + "kind": "file", + "label": "Codex native model reroute projection" + }, + { + "id": "codex-adapter-error-events", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1515, + "end": 1546, + "kind": "file", + "label": "Codex native errors normalized as runtime warning or error events" + }, + { + "id": "codex-adapter-tests", + "path": "apps/server/src/provider/Layers/CodexAdapter.test.ts", + "kind": "file", + "label": "Codex adapter lifecycle and canonical event behavior tests" + }, + { + "id": "claude-adapter-resume", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 656, + "end": 689, + "kind": "file", + "label": "Claude native session resume metadata validation" + }, + { + "id": "claude-adapter-runtime-events", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 2051, + "end": 2112, + "kind": "file", + "label": "Claude usage observations projected to canonical runtime events" + }, + { + "id": "claude-adapter-task-normalization", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 916, + "end": 1031, + "kind": "file", + "label": "Claude task and tool observations normalized for the product model" + }, + { + "id": "claude-adapter-permission-tests", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.test.ts", + "start": 338, + "end": 401, + "kind": "file", + "label": "Claude permission-mode and deferred interaction tests" + }, + { + "id": "claude-adapter-tests", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.test.ts", + "kind": "file", + "label": "Claude adapter stream, task, approval, input, resume, and usage tests" + }, + { + "id": "claude-driver-capability-probe", + "path": "apps/server/src/provider/Drivers/ClaudeDriver.ts", + "start": 63, + "end": 168, + "kind": "file", + "label": "Claude CLI discovery and capability snapshot construction" + }, + { + "id": "claude-skills-scanner", + "path": "apps/server/src/provider/Drivers/ClaudeSkills.ts", + "kind": "file", + "label": "Claude skill discovery and precedence scanner" + }, + { + "id": "acp-runtime-startup", + "path": "apps/server/src/provider/acp/AcpSessionRuntime.ts", + "start": 332, + "end": 418, + "kind": "file", + "label": "ACP session runtime construction, initialization, and queues" + }, + { + "id": "acp-runtime-prompt-cancel", + "path": "apps/server/src/provider/acp/AcpSessionRuntime.ts", + "start": 720, + "end": 783, + "kind": "file", + "label": "ACP prompt and cancellation operations" + }, + { + "id": "acp-runtime-event-queue", + "path": "apps/server/src/provider/acp/AcpSessionRuntime.ts", + "start": 691, + "end": 870, + "kind": "file", + "label": "ACP native and canonical event queue consumption" + }, + { + "id": "cursor-acp-spawn", + "path": "apps/server/src/provider/acp/CursorAcpSupport.ts", + "start": 34, + "end": 86, + "kind": "file", + "label": "Cursor ACP child launch and initialization options" + }, + { + "id": "cursor-extension-callbacks", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 479, + "end": 780, + "kind": "file", + "label": "Cursor ACP extension callbacks and canonical projections" + }, + { + "id": "cursor-steering-and-rollback", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 916, + "end": 1145, + "kind": "file", + "label": "Cursor steering, interruption, transcript rollback, and session stop" + }, + { + "id": "cursor-adapter-tests", + "path": "apps/server/src/provider/Layers/CursorAdapter.test.ts", + "kind": "file", + "label": "Cursor ACP adapter lifecycle and behavior tests" + }, + { + "id": "grok-extension-callbacks", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 530, + "end": 740, + "kind": "file", + "label": "Grok ACP and XAI extension callbacks" + }, + { + "id": "grok-interrupt-race", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 918, + "end": 1362, + "kind": "file", + "label": "Grok prompt, steering, and interruption race handling" + }, + { + "id": "grok-rollback-unsupported", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 1400, + "end": 1421, + "kind": "file", + "label": "explicitly unsupported Grok native rollback" + }, + { + "id": "grok-interrupt-tests", + "path": "apps/server/src/provider/Layers/GrokAdapter.test.ts", + "kind": "file", + "label": "Grok steering and interruption race tests" + }, + { + "id": "opencode-session-scope", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1139, + "end": 1426, + "kind": "file", + "label": "OpenCode scoped session construction and adoption" + }, + { + "id": "opencode-local-server-startup", + "path": "apps/server/src/provider/opencodeRuntime.ts", + "start": 477, + "end": 639, + "kind": "file", + "label": "scope-owned OpenCode child startup and stdout URL announcement" + }, + { + "id": "opencode-resume-adoption", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1204, + "end": 1387, + "kind": "file", + "label": "OpenCode resume lookup, cwd comparison, adoption, and fork" + }, + { + "id": "opencode-resume-cursor-codec", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 63, + "end": 83, + "kind": "file", + "label": "OpenCode current-version resume cursor decoder" + }, + { + "id": "opencode-resume-tests", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.test.ts", + "start": 304, + "end": 545, + "kind": "file", + "label": "OpenCode adoption, missing-session, and cwd-fork tests" + }, + { + "id": "opencode-event-pump", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 900, + "end": 1202, + "kind": "file", + "label": "session-filtered OpenCode event pump and normalization" + }, + { + "id": "opencode-interrupt-history-revert", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1510, + "end": 1701, + "kind": "file", + "label": "OpenCode abort, message history read, and counted session revert" + }, + { + "id": "opencode-adapter-tests", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.test.ts", + "kind": "file", + "label": "OpenCode adapter ownership, recovery, steering, and rollback tests" + }, + { + "id": "usage-live-admission", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 250, + "end": 257, + "kind": "file", + "label": "positive-used-token admission rule for live context telemetry" + }, + { + "id": "usage-window-validation", + "path": "apps/server/src/usage/UsageService.ts", + "start": 293, + "end": 350, + "kind": "file", + "label": "daily and bounded hourly usage window validation" + }, + { + "id": "usage-codex-transcript-parser", + "path": "apps/server/src/usage/usageTranscripts.ts", + "start": 200, + "end": 298, + "kind": "file", + "label": "Codex transcript model tracking, token deltas, and fork-copy suppression" + }, + { + "id": "usage-rate-table-acquisition", + "path": "apps/server/src/usage/UsageService.ts", + "start": 137, + "end": 184, + "kind": "file", + "label": "memory, disk, and remote LiteLLM rate-table acquisition" + }, + { + "id": "usage-scan-cache", + "path": "apps/server/src/usage/usageScanCache.ts", + "start": 1, + "end": 255, + "kind": "file", + "label": "per-file transcript scan cache, validation, pruning, and persistence" + }, + { + "id": "usage-merge-totals", + "path": "packages/shared/src/usageMerge.ts", + "start": 200, + "end": 416, + "kind": "file", + "label": "cross-environment bucket, source, session, and cost total reconstruction" + }, + { + "id": "usage-web-environment-queries", + "path": "apps/web/src/state/usage.ts", + "start": 40, + "end": 122, + "kind": "file", + "label": "web usage fan-out across connected environments and merge" + }, + { + "id": "usage-mobile-environment-queries", + "path": "apps/mobile/src/state/usage.ts", + "start": 43, + "end": 125, + "kind": "file", + "label": "mobile usage fan-out across connected environments and merge" + }, + { + "id": "usage-transcript-listing", + "path": "apps/server/src/usage/usageTranscriptReader.ts", + "start": 35, + "end": 74, + "kind": "file", + "label": "best-effort recursive transcript discovery" + }, + { + "id": "codex-followup-turn-queue", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 1806, + "end": 1864, + "kind": "file", + "label": "Codex turn/start follow-up queue and active interrupt target" + }, + { + "id": "codex-task-normalization", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 503, + "end": 750, + "kind": "file", + "label": "Codex multi-agent observations normalized to task lifecycle events" + }, + { + "id": "claude-task-event-lifecycle", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 2985, + "end": 3318, + "kind": "file", + "label": "Claude coordinator and member activity normalized to task events" + }, + { + "id": "cursor-plan-updates", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 414, + "end": 840, + "kind": "file", + "label": "Cursor plan and todo extensions normalized to product plan events" + }, + { + "id": "grok-plan-updates", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 464, + "end": 850, + "kind": "file", + "label": "Grok ACP plan observations normalized to product plan events" + }, + { + "id": "codex-provider-skills", + "path": "apps/server/src/provider/Layers/CodexProvider.ts", + "start": 400, + "end": 420, + "kind": "file", + "label": "Codex provider discovery requests native skills and models" + }, + { + "id": "codex-provider-feedback-command", + "path": "apps/server/src/provider/Layers/CodexProvider.ts", + "start": 600, + "end": 620, + "kind": "file", + "label": "Codex snapshot exposes discovered skills and a feedback slash command" + }, + { + "id": "claude-provider-skills-commands", + "path": "apps/server/src/provider/Layers/ClaudeProvider.ts", + "start": 920, + "end": 962, + "kind": "file", + "label": "Claude snapshot combines discovered skills and initialization commands" + }, + { + "id": "cursor-provider-snapshot", + "path": "apps/server/src/provider/Layers/CursorProvider.ts", + "start": 625, + "end": 650, + "kind": "file", + "label": "Cursor snapshot exposes models and probe state without skills or commands" + }, + { + "id": "grok-provider-snapshot", + "path": "apps/server/src/provider/Layers/GrokProvider.ts", + "start": 294, + "end": 311, + "kind": "file", + "label": "Grok snapshot exposes models and probe state without skills or commands" + }, + { + "id": "opencode-provider-skills", + "path": "apps/server/src/provider/Layers/OpenCodeProvider.ts", + "start": 445, + "end": 480, + "kind": "file", + "label": "OpenCode provider inventory flattened into models and skills" + }, + { + "id": "claude-local-rollback", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4480, + "end": 4494, + "kind": "file", + "label": "Claude adapter-local turn snapshot rollback and cursor refresh" + }, + { + "id": "turn-lifecycle-command-contract", + "path": "packages/contracts/src/orchestration.ts", + "start": 800, + "end": 872, + "kind": "file", + "label": "Turn start and interrupt command contracts" + }, + { + "id": "turn-lifecycle-runtime-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 121, + "end": 170, + "kind": "file", + "label": "Canonical provider runtime lifecycle event kinds" + }, + { + "id": "turn-lifecycle-turn-completion-payload", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 358, + "end": 375, + "kind": "file", + "label": "Provider turn completion payload" + }, + { + "id": "turn-lifecycle-engine-commit", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 197, + "end": 259, + "kind": "file", + "label": "Atomic event, projection, and receipt commit" + }, + { + "id": "turn-lifecycle-hot-reactor", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1405, + "end": 1409, + "kind": "file", + "label": "Hot command reactor stream without pending-work replay" + }, + { + "id": "turn-lifecycle-start-dedupe-cache", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 89, + "end": 325, + "kind": "file", + "label": "Bounded in-memory suppression cache for recently handled turn starts" + }, + { + "id": "turn-lifecycle-runtime-publication", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 286, + "end": 354, + "kind": "file", + "label": "Correlated runtime event publication" + }, + { + "id": "turn-lifecycle-runtime-adapter-subscription", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 372, + "end": 400, + "kind": "file", + "label": "Provider adapter event subscription" + }, + { + "id": "turn-lifecycle-runtime-fanout", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 1234, + "end": 1239, + "kind": "file", + "label": "Provider runtime hot-stream fan-out" + }, + { + "id": "turn-lifecycle-completion-finalization", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1840, + "end": 1874, + "kind": "file", + "label": "Turn-completion message and plan finalization" + }, + { + "id": "turn-lifecycle-interrupt-reactor", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1176, + "end": 1196, + "kind": "file", + "label": "Session-scoped provider interruption" + }, + { + "id": "turn-lifecycle-checkpoint-baseline", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 482, + "end": 530, + "kind": "file", + "label": "Pre-turn checkpoint baseline capture" + }, + { + "id": "turn-lifecycle-checkpoint-triggers", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 820, + "end": 937, + "kind": "file", + "label": "Runtime and domain stream checkpoint triggers" + }, + { + "id": "turn-lifecycle-runtime-receipts", + "path": "apps/server/src/orchestration/Layers/RuntimeReceiptBus.ts", + "start": 1, + "end": 39, + "kind": "file", + "label": "Test-only runtime milestone receipt bus" + }, + { + "id": "turn-lifecycle-client-liveness", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 255, + "end": 271, + "kind": "file", + "label": "Client thread connection liveness derivation" + }, + { + "id": "turn-lifecycle-client-turn-reducer", + "path": "packages/client-runtime/src/state/threadReducer.ts", + "start": 319, + "end": 425, + "kind": "file", + "label": "Client assistant-message and session turn reduction" + }, + { + "id": "turn-lifecycle-settlement-guards", + "path": "packages/client-runtime/src/state/threadSettled.ts", + "start": 286, + "end": 312, + "kind": "file", + "label": "Thread settlement eligibility guards" + }, + { + "id": "turn-lifecycle-waiting-ui-test", + "path": "apps/web/src/components/chat/ComposerPrimaryActions.test.tsx", + "start": 214, + "end": 219, + "kind": "file", + "label": "Stop action retained while provider waits for input" + }, + { + "id": "turn-lifecycle-runtime-tests", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts", + "start": 848, + "end": 920, + "kind": "file", + "label": "Lifecycle correlation and stale-event ingestion tests" + }, + { + "id": "turn-lifecycle-checkpoint-tests", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.test.ts", + "start": 457, + "end": 515, + "kind": "file", + "label": "Checkpoint trigger and capture tests" + }, + { + "id": "permission-runtime-mode-command", + "path": "packages/contracts/src/orchestration.ts", + "start": 784, + "end": 798, + "kind": "file", + "label": "Thread runtime-mode and interaction-mode commands" + }, + { + "id": "permission-runtime-mode-event", + "path": "packages/contracts/src/orchestration.ts", + "start": 1222, + "end": 1225, + "kind": "file", + "label": "Durable thread runtime-mode event payload" + }, + { + "id": "permission-claude-mode-map", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4138, + "end": 4412, + "kind": "file", + "label": "Claude runtime mode and permission callback mapping" + }, + { + "id": "permission-cursor-mode-routing", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 217, + "end": 733, + "kind": "file", + "label": "Cursor ACP session mode and permission routing" + }, + { + "id": "permission-grok-request-routing", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 666, + "end": 727, + "kind": "file", + "label": "Grok ACP permission request routing" + }, + { + "id": "permission-opencode-mode-map", + "path": "apps/server/src/provider/opencodeRuntime.ts", + "start": 371, + "end": 405, + "kind": "file", + "label": "OpenCode permission rules derived from T3 runtime mode" + }, + { + "id": "permission-opencode-request-routing", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 958, + "end": 1034, + "kind": "file", + "label": "OpenCode permission and question request normalization" + }, + { + "id": "permission-opencode-response-routing", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1579, + "end": 1618, + "kind": "file", + "label": "OpenCode permission and question replies" + }, + { + "id": "permission-runtime-activities", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 299, + "end": 539, + "kind": "file", + "label": "Canonical approval and input requests mapped to durable activities" + }, + { + "id": "permission-assistant-pause-flush", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1707, + "end": 1749, + "kind": "file", + "label": "Assistant buffer flush before provider interaction pauses" + }, + { + "id": "permission-response-reactor", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1199, + "end": 1285, + "kind": "file", + "label": "Approval and structured-input response intents forwarded to providers" + }, + { + "id": "permission-approval-projection", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1540, + "end": 1601, + "kind": "file", + "label": "Pending approval projection and stale-response recovery" + }, + { + "id": "permission-pending-storage", + "path": "apps/server/src/persistence/Layers/ProjectionPendingApprovals.ts", + "start": 16, + "end": 136, + "kind": "file", + "label": "SQLite-backed projected pending-approval upsert and query" + }, + { + "id": "permission-web-resolution", + "path": "apps/web/src/session-logic.ts", + "start": 410, + "end": 562, + "kind": "file", + "label": "Web pending approval and structured-input derivation" + }, + { + "id": "permission-mobile-resolution", + "path": "apps/mobile/src/state/use-selected-thread-requests.ts", + "start": 68, + "end": 191, + "kind": "file", + "label": "Mobile request derivation, drafts, and response commands" + }, + { + "id": "work-thread-record", + "path": "packages/contracts/src/orchestration.ts", + "start": 379, + "end": 423, + "kind": "file", + "label": "Durable thread record and lifecycle overlays" + }, + { + "id": "work-thread-shell", + "path": "packages/contracts/src/orchestration.ts", + "start": 449, + "end": 475, + "kind": "file", + "label": "Thread shell summary exposed to clients" + }, + { + "id": "work-thread-lifecycle-events", + "path": "packages/contracts/src/orchestration.ts", + "start": 1126, + "end": 1204, + "kind": "file", + "label": "Thread archive, settlement, snooze, and pin event payloads" + }, + { + "id": "work-thread-lifecycle-decisions", + "path": "apps/server/src/orchestration/decider.ts", + "start": 408, + "end": 810, + "kind": "file", + "label": "Archive, settle, snooze, pin, and reorder decision rules" + }, + { + "id": "work-task-linkage-ingestion", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 316, + "end": 359, + "kind": "file", + "label": "Server-stamped task identity and agent classification fields" + }, + { + "id": "work-task-activities", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 541, + "end": 742, + "kind": "file", + "label": "Task lifecycle and agent tool progress converted to activities" + }, + { + "id": "work-task-live-services", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1957, + "end": 2026, + "kind": "file", + "label": "Ephemeral plan progress and background liveness updates" + }, + { + "id": "work-subagent-fold", + "path": "packages/client-runtime/src/state/subagentRuntime.ts", + "start": 449, + "end": 679, + "kind": "file", + "label": "Order-tolerant activity fold into retained subagent state" + }, + { + "id": "work-agent-panel-model", + "path": "packages/client-runtime/src/state/subagentRuntime.ts", + "start": 680, + "end": 839, + "kind": "file", + "label": "Source-neutral Agents panel view model and rollups" + }, + { + "id": "work-web-agent-panel", + "path": "apps/web/src/components/AgentsPanel.tsx", + "start": 1, + "end": 190, + "kind": "file", + "label": "Web agent row states, activity, elapsed time, and task metrics" + }, + { + "id": "work-web-agent-summary", + "path": "apps/web/src/components/AgentsPanel.tsx", + "start": 490, + "end": 540, + "kind": "file", + "label": "Web Agents roster and aggregate footer" + }, + { + "id": "work-web-quiet-timeline", + "path": "apps/web/src/session-logic.ts", + "start": 783, + "end": 1115, + "kind": "file", + "label": "Web quiet-timeline filtering and agent spawn grouping" + }, + { + "id": "work-mobile-quiet-timeline", + "path": "apps/mobile/src/lib/threadActivity.ts", + "start": 283, + "end": 470, + "kind": "file", + "label": "Mobile work-log filtering and terminal task retention" + }, + { + "id": "work-mobile-work-log", + "path": "apps/mobile/src/features/threads/thread-work-log.tsx", + "start": 123, + "end": 274, + "kind": "file", + "label": "Mobile compact work-log presentation" + }, + { + "id": "work-background-liveness", + "path": "apps/server/src/orchestration/ThreadBackgroundLiveness.ts", + "start": 1, + "end": 173, + "kind": "file", + "label": "In-memory thread background liveness registry" + }, + { + "id": "work-plan-progress", + "path": "apps/server/src/orchestration/ThreadPlanProgress.ts", + "start": 1, + "end": 76, + "kind": "file", + "label": "In-memory current plan-step projection" + }, + { + "id": "work-provider-skill-contract", + "path": "packages/contracts/src/server.ts", + "start": 76, + "end": 97, + "kind": "file", + "label": "Provider slash-command and skill inventory contracts" + }, + { + "id": "work-provider-inventory-contract", + "path": "packages/contracts/src/server.ts", + "start": 180, + "end": 195, + "kind": "file", + "label": "Provider snapshots carry commands and skills as default-empty arrays" + }, + { + "id": "work-provider-skill-menu", + "path": "packages/client-runtime/src/providerSkills.ts", + "start": 19, + "end": 70, + "kind": "file", + "label": "Skill display, slash-menu inclusion, collision filtering, and source labels" + }, + { + "id": "work-web-skill-composer", + "path": "apps/web/src/components/chat/ChatComposer.tsx", + "start": 1108, + "end": 1165, + "kind": "file", + "label": "Web provider commands and skills composed into searchable menus" + }, + { + "id": "work-mobile-skill-composer", + "path": "apps/mobile/src/features/threads/ThreadComposer.tsx", + "start": 420, + "end": 530, + "kind": "file", + "label": "Mobile provider command and skill search composition" + }, + { + "id": "context-current-turn-payload", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 724, + "end": 760, + "kind": "file", + "label": "T3 constructs the visible turn payload and attachment paths" + }, + { + "id": "context-codex-turn-input", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 367, + "end": 423, + "kind": "file", + "label": "Codex native turn input assembled from the T3 request" + }, + { + "id": "context-codex-session-resume", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 466, + "end": 503, + "kind": "file", + "label": "Codex thread start or resume selection" + }, + { + "id": "context-codex-native-resume", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 1749, + "end": 1769, + "kind": "file", + "label": "Codex native continuation thread id returned as resume state" + }, + { + "id": "context-claude-resume-choice", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4170, + "end": 4254, + "kind": "file", + "label": "Claude native session resume and cursor selection" + }, + { + "id": "context-memory-codex-compaction", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 945, + "end": 975, + "kind": "file", + "label": "Codex compacted notification normalized as thread state" + }, + { + "id": "context-memory-claude-compaction", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 3122, + "end": 3143, + "kind": "file", + "label": "Claude compact boundary normalized as usage and thread state" + }, + { + "id": "context-client-snapshot-cache", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 129, + "end": 210, + "kind": "file", + "label": "Client thread snapshot cache hydration and persistence" + }, + { + "id": "context-client-event-cursor", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 619, + "end": 637, + "kind": "file", + "label": "Cached shell sequence seeds event-subscription catch-up" + }, + { + "id": "context-mobile-drafts", + "path": "apps/mobile/src/state/use-composer-drafts.ts", + "start": 146, + "end": 280, + "kind": "file", + "label": "Environment-scoped mobile composer draft persistence" + }, + { + "id": "context-mobile-outbox-storage", + "path": "apps/mobile/src/state/thread-outbox-storage.ts", + "start": 21, + "end": 145, + "kind": "file", + "label": "Mobile offline thread-command outbox persistence" + }, + { + "id": "context-thread-activity-limit", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 68, + "end": 76, + "kind": "file", + "label": "Thread detail snapshots cap recent activities at 500" + }, + { + "id": "context-thread-activity-query", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 1028, + "end": 1044, + "kind": "file", + "label": "Recent thread activities selected under the detail-window limit" + }, + { + "id": "checkpoint-model-contract", + "path": "packages/contracts/src/orchestration.ts", + "start": 312, + "end": 332, + "kind": "file", + "label": "Projected checkpoint identity, status, file summary, and completion fields" + }, + { + "id": "checkpoint-command-event-contract", + "path": "packages/contracts/src/orchestration.ts", + "start": 892, + "end": 1035, + "kind": "file", + "label": "Checkpoint revert, diff completion, and revert completion command payloads" + }, + { + "id": "checkpoint-event-discriminants", + "path": "packages/contracts/src/orchestration.ts", + "start": 1470, + "end": 1476, + "kind": "file", + "label": "Durable checkpoint-revert-requested and thread-reverted event discriminants" + }, + { + "id": "checkpoint-ref-naming", + "path": "apps/server/src/checkpointing/Utils.ts", + "start": 1, + "end": 24, + "kind": "file", + "label": "Base64url thread-scoped hidden checkpoint reference naming" + }, + { + "id": "checkpoint-git-capture", + "path": "apps/server/src/vcs/GitVcsDriver.ts", + "start": 708, + "end": 787, + "kind": "file", + "label": "Isolated-index workspace capture into a hidden Git ref" + }, + { + "id": "checkpoint-git-restore", + "path": "apps/server/src/vcs/GitVcsDriver.ts", + "start": 794, + "end": 828, + "kind": "file", + "label": "Checkpoint or HEAD fallback content restore, clean, and index reset" + }, + { + "id": "checkpoint-git-diff-delete", + "path": "apps/server/src/vcs/GitVcsDriver.ts", + "start": 830, + "end": 907, + "kind": "file", + "label": "Hidden-ref patch comparison and best-effort ref deletion attempts" + }, + { + "id": "checkpoint-status-derivation", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 65, + "end": 75, + "kind": "file", + "label": "Provider turn runtime state mapped to checkpoint status" + }, + { + "id": "checkpoint-diff-query-modes", + "path": "apps/server/src/checkpointing/CheckpointDiffQuery.ts", + "start": 37, + "end": 276, + "kind": "file", + "label": "Turn and full-thread hidden checkpoint diff queries" + }, + { + "id": "checkpoint-web-review-modes", + "path": "apps/web/src/components/DiffPanel.tsx", + "start": 203, + "end": 390, + "kind": "file", + "label": "Web selection of working-tree, branch, latest-turn, and prior-turn review modes" + }, + { + "id": "checkpoint-live-review-diffs", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2166, + "end": 2290, + "kind": "file", + "label": "Tracked plus untracked working-tree diff and merge-base branch-range diff" + }, + { + "id": "checkpoint-revert-preconditions", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 690, + "end": 770, + "kind": "file", + "label": "Revert read-model, bound-session, Git, turn-count, and target-ref preconditions" + }, + { + "id": "checkpoint-revert-effects", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 758, + "end": 838, + "kind": "file", + "label": "Ordered restore, workspace refresh, provider rollback, ref pruning, and completion dispatch" + }, + { + "id": "provider-rollback-interface", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 106, + "end": 117, + "kind": "file", + "label": "Provider adapter conversation rollback interface" + }, + { + "id": "provider-rollback-service", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 1080, + "end": 1119, + "kind": "file", + "label": "Bound provider session resolution and rollback delegation" + }, + { + "id": "codex-rollback-adapter", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1869, + "end": 1891, + "kind": "file", + "label": "Codex adapter rollback validation and runtime delegation" + }, + { + "id": "codex-rollback-native-request", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 1907, + "end": 1919, + "kind": "file", + "label": "Codex thread rollback native request and local session-state reset" + }, + { + "id": "cursor-rollback-local-history", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 1123, + "end": 1141, + "kind": "file", + "label": "Cursor adapter-local turn history truncation" + }, + { + "id": "opencode-rollback-native-revert", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1678, + "end": 1702, + "kind": "file", + "label": "OpenCode counted message-boundary session revert" + }, + { + "id": "workbench-terminal-contract", + "path": "packages/contracts/src/terminal.ts", + "start": 1, + "end": 234, + "kind": "file", + "label": "Terminal identity, commands, snapshots, metadata, and attach event schemas" + }, + { + "id": "workbench-terminal-manager-interface", + "path": "apps/server/src/terminal/Manager.ts", + "start": 123, + "end": 198, + "kind": "file", + "label": "Server terminal lifecycle and subscription service boundary" + }, + { + "id": "workbench-terminal-history-persistence", + "path": "apps/server/src/terminal/Manager.ts", + "start": 1355, + "end": 1496, + "kind": "file", + "label": "Debounced capped terminal history persistence and reload" + }, + { + "id": "workbench-terminal-history-reopen", + "path": "apps/server/src/terminal/Manager.ts", + "start": 2120, + "end": 2203, + "kind": "file", + "label": "Manager finalization and persisted-history restoration before PTY start" + }, + { + "id": "workbench-terminal-cleanup", + "path": "apps/server/src/orchestration/Layers/ThreadDeletionReactor.ts", + "start": 45, + "end": 65, + "kind": "file", + "label": "Thread deletion stops provider session and closes terminal history best-effort" + }, + { + "id": "workbench-terminal-web", + "path": "apps/web/src/components/ThreadTerminalDrawer.tsx", + "start": 337, + "end": 527, + "kind": "file", + "label": "Web terminal drawer subscribes to shared terminal state and renders Ghostty" + }, + { + "id": "workbench-terminal-mobile", + "path": "apps/mobile/src/features/terminal/ThreadTerminalPanel.tsx", + "start": 31, + "end": 210, + "kind": "file", + "label": "Mobile terminal lifecycle and native surface integration" + }, + { + "id": "workbench-project-file-rpc-contract", + "path": "packages/contracts/src/rpc.ts", + "start": 629, + "end": 656, + "kind": "file", + "label": "Authorized project entry search, list, read, and write RPC contracts" + }, + { + "id": "workbench-project-file-server", + "path": "apps/server/src/ws.ts", + "start": 1850, + "end": 1931, + "kind": "file", + "label": "Server workspace search, list, read, and write RPC handlers" + }, + { + "id": "workbench-project-file-client", + "path": "packages/client-runtime/src/state/projectCommands.ts", + "start": 42, + "end": 106, + "kind": "file", + "label": "Environment-scoped project file queries and serialized writes" + }, + { + "id": "workbench-mobile-files", + "path": "apps/mobile/src/features/files/FileTreeBrowser.tsx", + "start": 1, + "end": 145, + "kind": "file", + "label": "Mobile workspace tree and file preview surface" + }, + { + "id": "workbench-asset-contract", + "path": "packages/contracts/src/assets.ts", + "start": 1, + "end": 180, + "kind": "file", + "label": "Typed workspace file, attachment, and favicon asset resources" + }, + { + "id": "workbench-asset-claims", + "path": "apps/server/src/assets/AssetAccess.ts", + "start": 45, + "end": 97, + "kind": "file", + "label": "One-hour token TTL, preview extension allow-list, and narrow asset claims" + }, + { + "id": "workbench-asset-containment", + "path": "apps/server/src/assets/AssetAccess.ts", + "start": 133, + "end": 183, + "kind": "file", + "label": "Canonical real-path workspace containment checks" + }, + { + "id": "workbench-asset-issue", + "path": "apps/server/src/assets/AssetAccess.ts", + "start": 186, + "end": 425, + "kind": "file", + "label": "Scoped asset resolution, inspection, claim construction, and URL signing" + }, + { + "id": "workbench-asset-resolve", + "path": "apps/server/src/assets/AssetAccess.ts", + "start": 430, + "end": 523, + "kind": "file", + "label": "Signed asset signature, expiry, path, extension, and containment enforcement" + }, + { + "id": "workbench-asset-client", + "path": "packages/client-runtime/src/state/assets.ts", + "start": 38, + "end": 79, + "kind": "file", + "label": "Client asset URL refresh and expiry-aware state" + }, + { + "id": "workbench-mobile-workspace-asset", + "path": "apps/mobile/src/features/files/workspaceFileAssetUrl.ts", + "start": 1, + "end": 31, + "kind": "file", + "label": "Mobile workspace-file signed asset URL request" + }, + { + "id": "workbench-preview-contract", + "path": "packages/contracts/src/preview.ts", + "start": 145, + "end": 289, + "kind": "file", + "label": "Preview session snapshots, revisioned event stream, and navigation commands" + }, + { + "id": "workbench-preview-manager", + "path": "apps/server/src/preview/Manager.ts", + "start": 44, + "end": 442, + "kind": "file", + "label": "Server preview state, revision, event publication, and refresh coordination" + }, + { + "id": "workbench-preview-web-gate", + "path": "apps/web/src/routes/_chat.tsx", + "start": 111, + "end": 152, + "kind": "file", + "label": "Web runtime rejects in-app preview outside desktop" + }, + { + "id": "workbench-desktop-preview-preload", + "path": "apps/desktop/src/preload.ts", + "start": 167, + "end": 272, + "kind": "file", + "label": "Curated renderer-to-main preview IPC surface" + }, + { + "id": "workbench-desktop-preview-ipc", + "path": "apps/desktop/src/ipc/methods/preview.ts", + "start": 51, + "end": 92, + "kind": "file", + "label": "Desktop main-process preview IPC dispatch to PreviewManager" + }, + { + "id": "workbench-desktop-preview-manager", + "path": "apps/desktop/src/preview/Manager.ts", + "start": 1875, + "end": 2028, + "kind": "file", + "label": "Electron PreviewManager validates and owns guest WebContents" + }, + { + "id": "workbench-preview-automation-contract", + "path": "packages/contracts/src/previewAutomation.ts", + "start": 20, + "end": 113, + "kind": "file", + "label": "Preview automation host identity and operation vocabulary" + }, + { + "id": "workbench-preview-automation-broker", + "path": "apps/server/src/mcp/PreviewAutomationBroker.ts", + "start": 420, + "end": 587, + "kind": "file", + "label": "Environment-compatible desktop selection and sticky provider-session host lease" + }, + { + "id": "workbench-mcp-provider-preparation", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 237, + "end": 300, + "kind": "file", + "label": "Agent browser access setting gates MCP credential issue and revocation" + }, + { + "id": "workbench-mcp-session-start", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 645, + "end": 670, + "kind": "file", + "label": "MCP session is prepared before the provider adapter starts" + }, + { + "id": "workbench-mcp-registry", + "path": "apps/server/src/mcp/McpSessionRegistry.ts", + "start": 59, + "end": 201, + "kind": "file", + "label": "Hashed bearer registry, scoped preview capability, liveness, and eager revocation" + }, + { + "id": "workbench-mcp-http-auth", + "path": "apps/server/src/mcp/McpHttpServer.ts", + "start": 26, + "end": 97, + "kind": "file", + "label": "Provider-scoped bearer authentication supplies MCP invocation scope" + }, + { + "id": "workbench-mcp-http-toolkit", + "path": "apps/server/src/mcp/McpHttpServer.ts", + "start": 130, + "end": 226, + "kind": "file", + "label": "Authenticated preview toolkit registration on the MCP HTTP route" + }, + { + "id": "workbench-mcp-codex-injection", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1662, + "end": 1692, + "kind": "file", + "label": "Codex t3-code MCP URL and bearer-token environment injection" + }, + { + "id": "workbench-mcp-claude-injection", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4149, + "end": 4195, + "kind": "file", + "label": "Claude t3-code MCP HTTP server configuration injection" + }, + { + "id": "workbench-mcp-cursor-injection", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 534, + "end": 558, + "kind": "file", + "label": "Cursor ACP t3-code MCP server injection" + }, + { + "id": "workbench-mcp-grok-injection", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 572, + "end": 596, + "kind": "file", + "label": "Grok ACP t3-code MCP server injection" + }, + { + "id": "workbench-mcp-opencode-injection", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1234, + "end": 1249, + "kind": "file", + "label": "OpenCode t3-code MCP registration only for T3-owned local servers" + }, + { + "id": "workbench-vcs-contract", + "path": "packages/contracts/src/vcs.ts", + "start": 1, + "end": 36, + "kind": "file", + "label": "VCS driver identity, freshness, and capability flags" + }, + { + "id": "workbench-git-worktree-contract", + "path": "packages/contracts/src/git.ts", + "start": 76, + "end": 165, + "kind": "file", + "label": "Server-addressed VCS reference and worktree operation inputs" + }, + { + "id": "worktree-local-selected-path", + "path": "apps/mobile/src/lib/projectThreadStartTurn.ts", + "start": 50, + "end": 88, + "kind": "file", + "label": "Mobile local bootstrap retains a supplied existing workspace path" + }, + { + "id": "worktree-runtime-cwd-resolution", + "path": "apps/server/src/checkpointing/Utils.ts", + "start": 12, + "end": 27, + "kind": "file", + "label": "Runtime workspace resolution prefers thread worktreePath before project root" + }, + { + "id": "worktree-setup-launch-outcome", + "path": "apps/server/src/ws.ts", + "start": 846, + "end": 959, + "kind": "file", + "label": "Bootstrap setup launch records failure or started activity outcomes" + }, + { + "id": "worktree-thread-deletion-effects", + "path": "apps/server/src/orchestration/Layers/ThreadDeletionReactor.ts", + "start": 45, + "end": 65, + "kind": "file", + "label": "Thread deletion stops provider session and closes terminal history" + }, + { + "id": "worktree-web-orphan-cleanup", + "path": "apps/web/src/hooks/useThreadActions.ts", + "start": 308, + "end": 453, + "kind": "file", + "label": "Web-confirmed orphaned-worktree removal follows durable thread deletion" + }, + { + "id": "workbench-pr-rpc-contract", + "path": "packages/contracts/src/rpc.ts", + "start": 289, + "end": 603, + "kind": "file", + "label": "Pull-request list, detail, action, review, and invalidation RPC surface" + }, + { + "id": "workbench-pr-http-contract", + "path": "packages/contracts/src/environmentHttp.ts", + "start": 533, + "end": 547, + "kind": "file", + "label": "Authenticated HTTP endpoint for large pull-request diff payloads" + }, + { + "id": "workbench-pr-project-resolution", + "path": "apps/server/src/pullRequest/PullRequestService.ts", + "start": 585, + "end": 740, + "kind": "file", + "label": "Eligible repository resolution, worktree de-duplication, and alternate viewer roots" + }, + { + "id": "workbench-pr-invalidation", + "path": "apps/server/src/pullRequest/PullRequestService.ts", + "start": 2110, + "end": 2145, + "kind": "file", + "label": "Successful PR mutations invalidate reference and listing epochs" + }, + { + "id": "workbench-pr-web-capability", + "path": "apps/web/src/routes/_chat.pull-requests.tsx", + "start": 223, + "end": 274, + "kind": "file", + "label": "Web PR route selects connected environments advertising pull-request capability" + }, + { + "id": "workbench-mobile-external-pr", + "path": "apps/mobile/src/features/threads/ThreadGitControls.tsx", + "start": 149, + "end": 188, + "kind": "file", + "label": "Mobile Git controls open an existing pull request externally" + }, + { + "id": "workbench-mobile-vcs-state", + "path": "apps/mobile/src/state/vcs.ts", + "start": 1, + "end": 9, + "kind": "file", + "label": "Mobile re-exports shared server-backed VCS state" + }, + { + "id": "permission-runtime-mode-decider", + "path": "apps/server/src/orchestration/decider.ts", + "start": 878, + "end": 900, + "kind": "file", + "label": "Runtime-mode command validation and durable event creation" + }, + { + "id": "permission-turn-start-stored-mode", + "path": "apps/server/src/orchestration/decider.ts", + "start": 926, + "end": 995, + "kind": "file", + "label": "Turn-start event takes runtime and interaction modes from stored thread state" + }, + { + "id": "permission-response-intent-decider", + "path": "apps/server/src/orchestration/decider.ts", + "start": 1061, + "end": 1110, + "kind": "file", + "label": "Approval and structured-input responses become durable requested events" + }, + { + "id": "permission-claude-special-input", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 3966, + "end": 4000, + "kind": "file", + "label": "Claude AskUserQuestion and ExitPlanMode are intercepted before full-access shortcut" + }, + { + "id": "permission-grok-full-access", + "path": "apps/server/src/provider/Layers/GrokAdapter.ts", + "start": 182, + "end": 203, + "kind": "file", + "label": "Grok full-access selects allow-always or allow-once when offered" + }, + { + "id": "permission-pinned-activities", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 1256, + "end": 1342, + "kind": "file", + "label": "Unresolved approval and user-input request activities are pinned outside the recent window" + }, + { + "id": "work-task-stable-streams", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 541, + "end": 742, + "kind": "file", + "label": "Only task progress, typed usage, and agent tool heartbeats use stable latest-state activity ids" + }, + { + "id": "work-subagent-legacy-classification", + "path": "packages/client-runtime/src/state/subagentRuntime.ts", + "start": 112, + "end": 120, + "kind": "file", + "label": "Legacy activity without server-stamped agentKind falls back to background classification" + }, + { + "id": "work-mobile-skill-search", + "path": "apps/mobile/src/features/threads/composerSlashSkillSearch.ts", + "start": 1, + "end": 16, + "kind": "file", + "label": "Mobile skill search matches enabled inventory without web collision filtering" + }, + { + "id": "work-web-skill-insertion", + "path": "apps/web/src/components/chat/ChatComposer.tsx", + "start": 1807, + "end": 1823, + "kind": "file", + "label": "Web skill selection inserts provider-facing dollar-prefixed prompt syntax" + }, + { + "id": "work-mobile-skill-insertion", + "path": "apps/mobile/src/features/threads/ThreadComposer.tsx", + "start": 601, + "end": 617, + "kind": "file", + "label": "Mobile skill selection inserts provider-facing dollar-prefixed prompt syntax" + }, + { + "id": "turn-lifecycle-web-mode-persist", + "path": "apps/web/src/components/ChatView.tsx", + "start": 5549, + "end": 5563, + "kind": "file", + "label": "Web persists selected model and modes on the thread before sending the turn" + }, + { + "id": "turn-lifecycle-domain-baseline", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 629, + "end": 680, + "kind": "file", + "label": "Durable turn-start or user-message events trigger the early checkpoint baseline" + }, + { + "id": "project-cli-add", + "path": "apps/server/src/cli/project.ts", + "start": 444, + "end": 491, + "kind": "file", + "label": "CLI project add normalizes one explicit root and dispatches project.create" + }, + { + "id": "project-startup-cwd-bootstrap", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 196, + "end": 249, + "kind": "file", + "label": "Optional startup flag registers the configured cwd and creates an initial local thread" + }, + { + "id": "project-client-add-path", + "path": "packages/client-runtime/src/operations/projects.ts", + "start": 256, + "end": 316, + "kind": "file", + "label": "Client validates one chosen add-project path and builds project.create" + }, + { + "id": "project-clone-registration", + "path": "apps/web/src/components/CommandPalette.tsx", + "start": 1950, + "end": 1980, + "kind": "file", + "label": "Web resolves one clone destination and registers the returned checkout through the normal add-project flow" + }, + { + "id": "project-script-durable-save", + "path": "apps/web/src/components/ChatView.tsx", + "start": 3188, + "end": 3252, + "kind": "file", + "label": "Imported or edited scripts are saved into the durable project scripts list" + }, + { + "id": "project-script-setup-selection", + "path": "packages/shared/src/projectScripts.ts", + "start": 31, + "end": 37, + "kind": "file", + "label": "Setup selects the first opted-in durable project script" + }, + { + "id": "client-connection-resolver", + "path": "packages/client-runtime/src/connection/resolver.ts", + "start": 51, + "end": 280, + "kind": "file", + "label": "Target-specific preparation into a prepared connection" + }, + { + "id": "client-connection-driver", + "path": "packages/client-runtime/src/connection/driver.ts", + "start": 15, + "end": 61, + "kind": "file", + "label": "Resolver, session factory, and staged connection lease" + }, + { + "id": "client-registry-supervisor-lease", + "path": "packages/client-runtime/src/connection/registry.ts", + "start": 171, + "end": 334, + "kind": "file", + "label": "Per-environment supervisor lease lock and scoped lifecycle" + }, + { + "id": "client-connection-supervisor-state", + "path": "packages/client-runtime/src/connection/supervisor.ts", + "start": 198, + "end": 247, + "kind": "file", + "label": "Supervisor service state and initial lifecycle" + }, + { + "id": "client-connection-supervisor-retry", + "path": "packages/client-runtime/src/connection/supervisor.ts", + "start": 678, + "end": 753, + "kind": "file", + "label": "Transient retry, backoff, and blocked retry policy" + }, + { + "id": "client-rpc-dynamic-subscription", + "path": "packages/client-runtime/src/rpc/client.ts", + "start": 170, + "end": 280, + "kind": "file", + "label": "Session-aware dynamic subscription replacement" + }, + { + "id": "client-state-runtime-families", + "path": "packages/client-runtime/src/state/runtime.ts", + "start": 480, + "end": 567, + "kind": "file", + "label": "Environment-keyed Atom query, subscription, and command families" + }, + { + "id": "client-shell-reconnect", + "path": "packages/client-runtime/src/state/shell.ts", + "start": 52, + "end": 254, + "kind": "file", + "label": "Shell cache persistence and session-aware snapshot/resume" + }, + { + "id": "client-thread-race-guards", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 134, + "end": 530, + "kind": "file", + "label": "Thread cache, cursor, epoch, and older-page race guards" + }, + { + "id": "client-thread-subscription", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 534, + "end": 693, + "kind": "file", + "label": "Thread session subscription, capability gating, and older-page request queue" + }, + { + "id": "mobile-stack-continuity-workers", + "path": "apps/mobile/src/Stack.tsx", + "start": 338, + "end": 405, + "kind": "file", + "label": "Route-persistent outbox drain, share presentation, and adaptive workspace layout" + }, + { + "id": "mobile-platform-connection-services", + "path": "apps/mobile/src/connection/platform.ts", + "start": 29, + "end": 229, + "kind": "file", + "label": "Mobile connectivity, wakeups, capabilities, and environment-owned cleanup" + }, + { + "id": "mobile-environment-cache-store", + "path": "apps/mobile/src/connection/environment-cache-store.ts", + "start": 1, + "end": 247, + "kind": "file", + "label": "Schema-versioned SQLite adapters for environment client caches" + }, + { + "id": "mobile-persistence-layer", + "path": "apps/mobile/src/persistence/layer.ts", + "start": 1, + "end": 16, + "kind": "file", + "label": "Mobile database, secure storage, preferences, and cache layer composition" + }, + { + "id": "mobile-secure-connection-catalog", + "path": "apps/mobile/src/connection/catalog-store.ts", + "start": 1, + "end": 121, + "kind": "file", + "label": "Locked and migrated connection catalog in mobile secure storage" + }, + { + "id": "mobile-storage-domain", + "path": "apps/mobile/src/persistence/mobile-storage.ts", + "start": 16, + "end": 264, + "kind": "file", + "label": "Saved connections, device registration identity, and shortcuts storage domain" + }, + { + "id": "mobile-outbox-model", + "path": "apps/mobile/src/state/thread-outbox-model.ts", + "start": 24, + "end": 227, + "kind": "file", + "label": "Versioned queued-turn model, delivery decision, and retry classification" + }, + { + "id": "mobile-outbox-manager", + "path": "apps/mobile/src/state/thread-outbox-manager.ts", + "start": 40, + "end": 227, + "kind": "file", + "label": "Serialized optimistic and durable mobile outbox manager" + }, + { + "id": "mobile-share-config", + "path": "apps/mobile/app.config.ts", + "start": 111, + "end": 153, + "kind": "file", + "label": "iOS widget and cross-platform incoming-share capability configuration" + }, + { + "id": "mobile-share-provider", + "path": "apps/mobile/src/features/sharing/IncomingShareProvider.tsx", + "start": 1, + "end": 316, + "kind": "file", + "label": "Native payload ingestion, persisted inbox projection, and app-active refresh" + }, + { + "id": "mobile-share-inbox", + "path": "apps/mobile/src/features/sharing/incoming-share-inbox.ts", + "start": 31, + "end": 193, + "kind": "file", + "label": "Serialized incoming-share ingestion, reservation, release, and consumption" + }, + { + "id": "mobile-share-storage", + "path": "apps/mobile/src/features/sharing/incoming-share-storage.ts", + "start": 1, + "end": 80, + "kind": "file", + "label": "One persisted JSON document per incoming mobile share" + }, + { + "id": "mobile-thread-feed", + "path": "apps/mobile/src/features/threads/ThreadFeed.tsx", + "start": 1475, + "end": 2165, + "kind": "file", + "label": "Virtualized native thread feed, visible-position preservation, and keyboard-aware end following" + }, + { + "id": "mobile-native-review-adapter", + "path": "apps/mobile/src/features/review/nativeReviewDiffAdapter.ts", + "start": 1, + "end": 526, + "kind": "file", + "label": "Parsed review diff to cached native row and theme model" + }, + { + "id": "mobile-hardware-keyboard", + "path": "apps/mobile/src/features/keyboard/hardwareKeyboardCommands.ts", + "start": 1, + "end": 78, + "kind": "file", + "label": "Route-scoped most-recent-first hardware keyboard command dispatch" + }, + { + "id": "mobile-agent-activity-widget", + "path": "apps/mobile/src/widgets/AgentActivity.tsx", + "start": 21, + "end": 381, + "kind": "file", + "label": "iOS Agent Activity widget and Live Activity projection" + }, + { + "id": "mobile-update-flow", + "path": "apps/mobile/src/features/updates/app-updates.ts", + "start": 253, + "end": 539, + "kind": "file", + "label": "OTA check, download, deferral, persistence flush, and reload coordination" + }, + { + "id": "mobile-foreground-handoff", + "path": "apps/mobile/src/lib/foreground-handoff.ts", + "start": 1, + "end": 22, + "kind": "file", + "label": "Reference-counted app-initiated native foreground handoff guard" + }, + { + "id": "desktop-primary-platform-selection", + "path": "apps/desktop/src/backend/DesktopBackendConfiguration.ts", + "start": 677, + "end": 743, + "kind": "file", + "label": "Host-local primary configuration with optional Windows WSL-only resolution" + }, + { + "id": "desktop-backend-pool-lifecycle", + "path": "apps/desktop/src/backend/DesktopBackendPool.ts", + "start": 139, + "end": 440, + "kind": "file", + "label": "Primary lifetime, per-instance child scopes, registration, and unregister protection" + }, + { + "id": "desktop-backend-process-supervision", + "path": "apps/desktop/src/backend/DesktopBackendManager.ts", + "start": 626, + "end": 1150, + "kind": "file", + "label": "Independent instance state, readiness, restart scheduling, and graceful stop" + }, + { + "id": "desktop-backend-process-wiring", + "path": "apps/desktop/src/backend/DesktopBackendManager.ts", + "start": 440, + "end": 610, + "kind": "file", + "label": "Child-process bootstrap channels, diagnostics demand, and repeated HTTP readiness" + }, + { + "id": "desktop-wsl-reconciliation", + "path": "apps/desktop/src/wsl/DesktopWslBackend.ts", + "start": 97, + "end": 265, + "kind": "file", + "label": "Serialized WSL secondary reconciliation and WSL-only primary exclusion" + }, + { + "id": "desktop-ssh-gateway", + "path": "apps/desktop/src/ssh/DesktopSshEnvironment.ts", + "start": 51, + "end": 166, + "kind": "file", + "label": "Desktop SSH discovery, managed remote environment, and password-prompt gateway" + }, + { + "id": "desktop-lifecycle-quit", + "path": "apps/desktop/src/app/DesktopLifecycle.ts", + "start": 190, + "end": 254, + "kind": "file", + "label": "Ordinary, updater-controlled, window, activation, and signal quit paths" + }, + { + "id": "desktop-app-pool-shutdown", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 295, + "end": 315, + "kind": "file", + "label": "Concurrent graceful shutdown of every registered local backend instance" + }, + { + "id": "distribution-root-build-scripts", + "path": "package.json", + "start": 21, + "end": 45, + "kind": "file", + "label": "Monorepo build and desktop artifact entrypoints" + }, + { + "id": "distribution-cli-package", + "path": "apps/server/package.json", + "start": 1, + "end": 52, + "kind": "file", + "label": "Published t3 package metadata, executable, payload, and runtime dependencies" + }, + { + "id": "distribution-cli-build-publish", + "path": "apps/server/scripts/cli.ts", + "start": 143, + "end": 304, + "kind": "file", + "label": "CLI bundle composition and temporary npm publication metadata" + }, + { + "id": "distribution-cli-bundle-config", + "path": "apps/server/vite.config.ts", + "start": 23, + "end": 75, + "kind": "file", + "label": "Server bundling policy and release-time public configuration" + }, + { + "id": "distribution-desktop-build-config", + "path": "scripts/build-desktop-artifact.ts", + "start": 2038, + "end": 2177, + "kind": "file", + "label": "Electron-builder platform, artifact, update, protocol, and signing configuration" + }, + { + "id": "distribution-desktop-stage-pipeline", + "path": "scripts/build-desktop-artifact.ts", + "start": 2650, + "end": 3070, + "kind": "file", + "label": "Desktop staging, dependency closure, sidecars, and artifact build pipeline" + }, + { + "id": "distribution-release-workflow", + "path": ".github/workflows/release.yml", + "start": 1, + "end": 1156, + "kind": "file", + "label": "Stable and nightly release graph" + }, + { + "id": "distribution-release-artifact-matrix", + "path": ".github/workflows/release.yml", + "start": 342, + "end": 397, + "kind": "file", + "label": "Desktop release artifact matrix and latent Windows arm64 entry" + }, + { + "id": "distribution-release-publish-dag", + "path": ".github/workflows/release.yml", + "start": 709, + "end": 1035, + "kind": "file", + "label": "CLI, GitHub Release, AUR, and hosted-web dependency graph" + }, + { + "id": "distribution-mobile-production-workflow", + "path": ".github/workflows/mobile-eas-production.yml", + "start": 1, + "end": 290, + "kind": "file", + "label": "Store-build reconciliation and fingerprint-gated production OTA workflow" + }, + { + "id": "distribution-mobile-eas-profiles", + "path": "apps/mobile/eas.json", + "start": 1, + "end": 63, + "kind": "file", + "label": "Development, preview, production, and store submission profiles" + }, + { + "id": "distribution-mobile-app-config", + "path": "apps/mobile/app.config.ts", + "start": 159, + "end": 235, + "kind": "file", + "label": "Native identities, runtime fingerprint, OTA source, and platform configuration" + }, + { + "id": "distribution-hosted-router", + "path": "apps/web/vercel.ts", + "start": 1, + "end": 66, + "kind": "file", + "label": "Release-controlled hosted channel router and disabled Git deploys" + }, + { + "id": "distribution-marketing-release-fetch", + "path": "apps/marketing/src/lib/releases.ts", + "start": 1, + "end": 30, + "kind": "file", + "label": "Latest GitHub Release lookup and session cache" + }, + { + "id": "distribution-marketing-download-page", + "path": "apps/marketing/src/pages/download.astro", + "start": 1, + "end": 132, + "kind": "file", + "label": "Desktop asset and mobile store download resolution" + }, + { + "id": "distribution-aur-workflow", + "path": ".github/workflows/publish-aur.yml", + "start": 1, + "end": 65, + "kind": "file", + "label": "Containerized AUR validation and publishing workflow" + }, + { + "id": "distribution-aur-release-script", + "path": "packaging/aur/scripts/release.sh", + "start": 1, + "end": 91, + "kind": "file", + "label": "Release asset digest verification, package build, and AUR push" + }, + { + "id": "distribution-aur-stable-package", + "path": "packaging/aur/t3code-bin/PKGBUILD", + "start": 1, + "end": 104, + "kind": "file", + "label": "Stable AppImage extraction and Arch package layout" + }, + { + "id": "distribution-aur-nightly-package", + "path": "packaging/aur/t3code-nightly-bin/PKGBUILD", + "start": 1, + "end": 105, + "kind": "file", + "label": "Nightly AppImage extraction and channel-isolated Arch package layout" + }, + { + "id": "release-operations-guide", + "path": "docs/operations/release.md", + "start": 1, + "end": 281, + "kind": "file", + "label": "Release triggers, artifacts, hosted channels, exact-version invariant, and updater assets" + }, + { + "id": "release-desktop-update-service", + "path": "apps/desktop/src/updates/DesktopUpdates.ts", + "start": 151, + "end": 760, + "kind": "file", + "label": "Desktop updater state, channel, polling, download, install, and IPC ownership" + }, + { + "id": "release-desktop-update-reducers", + "path": "apps/desktop/src/updates/updateMachine.ts", + "start": 1, + "end": 209, + "kind": "file", + "label": "Pure desktop updater state transitions" + }, + { + "id": "release-server-update-capability", + "path": "packages/contracts/src/environment.ts", + "start": 31, + "end": 92, + "kind": "file", + "label": "Server version and self-update capability negotiation" + }, + { + "id": "release-server-self-update", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 30, + "end": 199, + "kind": "file", + "label": "Exact-version preparation, preflight, and stable-launcher handoff" + }, + { + "id": "release-server-update-client", + "path": "packages/client-runtime/src/state/server.ts", + "start": 517, + "end": 683, + "kind": "file", + "label": "Client update progress, reconnect nudging, and ready-event correlation" + }, + { + "id": "release-server-update-architecture", + "path": "docs/internals/server-updates.md", + "start": 1, + "end": 99, + "kind": "file", + "label": "Stable launcher, reversible trial, database snapshot, and client correlation" + }, + { + "id": "release-mobile-update-runtime", + "path": "apps/mobile/src/features/updates/app-updates.ts", + "start": 1, + "end": 480, + "kind": "file", + "label": "Expo update check, download, foreground deferral, flush, and safe reload" + }, + { + "id": "telemetry-analytics-service", + "path": "apps/server/src/telemetry/AnalyticsService.ts", + "start": 1, + "end": 186, + "kind": "file", + "label": "Best-effort bounded PostHog product analytics" + }, + { + "id": "telemetry-identity-resolution", + "path": "apps/server/src/telemetry/Identify.ts", + "start": 1, + "end": 300, + "kind": "file", + "label": "Hashed account or installation-scoped analytics identity selection" + }, + { + "id": "telemetry-server-observability", + "path": "apps/server/src/observability/Layers/Observability.ts", + "start": 1, + "end": 94, + "kind": "file", + "label": "Server logs, local traces, optional OTLP traces, and optional metrics" + }, + { + "id": "telemetry-browser-client-tracing", + "path": "apps/web/src/observability/clientTracing.ts", + "start": 16, + "end": 133, + "kind": "file", + "label": "Web tracer delegates OTLP batches through the selected primary environment" + }, + { + "id": "telemetry-browser-ingest-route", + "path": "apps/server/src/http.ts", + "start": 141, + "end": 199, + "kind": "file", + "label": "Operate-scoped browser trace ingestion and optional remote forwarding" + }, + { + "id": "telemetry-resource-architecture", + "path": "docs/internals/resource-telemetry.md", + "start": 1, + "end": 352, + "kind": "file", + "label": "Native resource telemetry topology, demand, retention, and packaging" + }, + { + "id": "telemetry-resource-server", + "path": "apps/server/src/resourceTelemetry", + "kind": "directory", + "label": "Resource-monitor supervision, merge, history, and attribution services" + }, + { + "id": "telemetry-resource-native", + "path": "native/resource-monitor/src", + "kind": "directory", + "label": "Standalone Rust resource monitor implementation" + }, + { + "id": "access-target-model", + "path": "packages/client-runtime/src/connection/model.ts", + "start": 4, + "end": 54, + "kind": "file", + "label": "Primary, Bearer, Relay, and SSH target union" + }, + { + "id": "access-connection-catalog", + "path": "packages/client-runtime/src/connection/catalog.ts", + "start": 19, + "end": 105, + "kind": "file", + "label": "Persisted target, profile, credential, and registration catalog" + }, + { + "id": "access-connection-resolver", + "path": "packages/client-runtime/src/connection/resolver.ts", + "start": 51, + "end": 277, + "kind": "file", + "label": "Route-specific target resolution into a common prepared connection" + }, + { + "id": "access-desktop-exposure", + "path": "apps/desktop/src/backend/DesktopServerExposure.ts", + "start": 101, + "end": 133, + "kind": "file", + "label": "Loopback versus network bind and LAN endpoint advertisement" + }, + { + "id": "access-environment-auth-policy", + "path": "apps/server/src/auth/EnvironmentAuthPolicy.ts", + "start": 16, + "end": 47, + "kind": "file", + "label": "Runtime-mode and reachability-derived authentication policy" + }, + { + "id": "access-pairing-grant", + "path": "apps/server/src/auth/PairingGrantStore.ts", + "start": 379, + "end": 567, + "kind": "file", + "label": "Time-bounded one-time pairing issuance and atomic consumption" + }, + { + "id": "access-pairing-delegation", + "path": "apps/server/src/auth/http.ts", + "start": 335, + "end": 355, + "kind": "file", + "label": "Access-write and delegated-scope subset enforcement" + }, + { + "id": "access-bearer-registration", + "path": "packages/client-runtime/src/connection/onboarding.ts", + "start": 73, + "end": 211, + "kind": "file", + "label": "Pairing exchange to associated bearer target, profile, and credential" + }, + { + "id": "access-tailscale-endpoints", + "path": "apps/desktop/src/backend/tailscaleEndpointProvider.ts", + "start": 19, + "end": 145, + "kind": "file", + "label": "Tailnet IP and MagicDNS HTTPS advertised endpoints" + }, + { + "id": "access-tailscale-serve", + "path": "packages/tailscale/src/tailscale.ts", + "start": 278, + "end": 365, + "kind": "file", + "label": "Tailscale HTTPS URL and Serve proxy lifecycle" + }, + { + "id": "access-desktop-ssh-gateway", + "path": "apps/desktop/src/ssh/DesktopSshEnvironment.ts", + "start": 127, + "end": 155, + "kind": "file", + "label": "Desktop-owned SSH ensure and disconnect gateway" + }, + { + "id": "access-ssh-forward", + "path": "packages/ssh/src/tunnel.ts", + "start": 942, + "end": 1442, + "kind": "file", + "label": "Remote server launch, local SSH forwarding, readiness, and finalization" + }, + { + "id": "access-ssh-registration", + "path": "packages/client-runtime/src/connection/onboarding.ts", + "start": 213, + "end": 243, + "kind": "file", + "label": "SSH environment target and profile registration" + }, + { + "id": "connect-relay-control-plane", + "path": "infra/relay/README.md", + "start": 6, + "end": 29, + "kind": "file", + "label": "Relay responsibility and direct post-launch environment traffic" + }, + { + "id": "connect-maintainer-doc", + "path": "docs/internals/t3-connect.md", + "start": 1, + "end": 33, + "kind": "file", + "label": "Maintainer-documented Clerk application and OAuth configuration" + }, + { + "id": "remote-explicit-future-work", + "path": "docs/internals/remote.md", + "start": 223, + "end": 229, + "kind": "file", + "label": "Explicitly unbuilt remote endpoint-provider, callback-broker, and multi-environment work" + }, + { + "id": "plan-ui-transition", + "path": "apps/web/src/planAgentSelectionHeal.tsx", + "start": 10, + "end": 51, + "kind": "file", + "label": "Web legacy plan-mode selection healing after settings hydration" + }, + { + "id": "plan-ui-capability-filter", + "path": "apps/web/src/providerModels.ts", + "start": 80, + "end": 112, + "kind": "file", + "label": "Legacy plan-mode capability filtering before model dispatch" + }, + { + "id": "plan-ui-mobile-legacy", + "path": "apps/mobile/src/persistence/mobile-preferences.ts", + "start": 34, + "end": 45, + "kind": "file", + "label": "Device-local mobile legacy plan-mode preference" + } +] diff --git a/sources/t3code.lock.json b/sources/t3code.lock.json new file mode 100644 index 0000000..58584c2 --- /dev/null +++ b/sources/t3code.lock.json @@ -0,0 +1,14 @@ +{ + "repository": "https://github.com/pingdotgg/t3code", + "commit": "fa219001dc2f14cfd9c7774c2c03c153359144be", + "shortCommit": "fa219001d", + "branch": "main", + "capturedAt": "2026-08-24T00:00:00+03:00", + "sourceDirHint": "../t3code", + "inventoryRulesVersion": 1, + "productionFiles": 1844, + "productionLines": 533213, + "testFiles": 881, + "testLines": 247766, + "notes": "Recomputed from pinned Git objects by scripts/inventory-source.mjs. Counts include tracked implementation/build source extensions, exclude assets and .repos, and classify test/spec/fixture paths separately; generated protocol source remains included." +} diff --git a/src/components/AccessTransportLab.astro b/src/components/AccessTransportLab.astro new file mode 100644 index 0000000..9d7bfeb --- /dev/null +++ b/src/components/AccessTransportLab.astro @@ -0,0 +1,173 @@ +--- +interface Props { + id: string; +} + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("AccessTransportLab requires a stable kebab-case id."); +} + +const labId = `access-transport-${id}`; +const routes = { + primary: { + label: "Host-local primary", + target: "Primary connection target", + launch: "Desktop launches the host-local backend; a browser may already be on its same origin.", + access: "Loopback HTTP and WebSocket bases are used directly. Primary auth is supplied by the platform when it has one.", + boundary: "A loopback bind is a reachability limit. It does not make every renderer or process on the machine an authority holder.", + registration: "Platform registration reconciles the primary; it is not a user-saved bearer profile.", + }, + bearer: { + label: "Paired bearer over LAN or HTTPS", + target: "Bearer connection target", + launch: "The server is already running. Pairing is an enrollment action, not a process-launch protocol.", + access: "The client uses the saved HTTP/WebSocket profile and a saved bearer credential, then obtains the scoped session material required by the environment.", + boundary: "The advertised route determines who can attempt enrollment; scopes and credential lifecycle decide what the enrolled client may do.", + registration: "A bearer registration binds one connection id to both a profile and credential. The resolver checks the profile before it prepares the route.", + }, + tailscale: { + label: "Paired bearer through Tailnet", + target: "Bearer connection target — not a Tailscale target", + launch: "The server is already running. Tailscale may provide an IP endpoint or a MagicDNS HTTPS endpoint through Tailscale Serve.", + access: "Pairing and subsequent bearer access use the selected Tailnet endpoint just as they use another reachable endpoint.", + boundary: "Tailscale changes endpoint provisioning and private-network reachability. It does not add a fifth connection-target kind or replace application authorization.", + registration: "The saved connection remains Bearer. An endpoint provider advertises candidate routes; it does not become the durable connection model.", + }, + ssh: { + label: "Desktop-managed SSH", + target: "SSH connection target", + launch: "Electron main asks the SSH manager to start or reuse the remote server, then reserves a local loopback port and opens an SSH forward.", + access: "The renderer connects to the forwarded local HTTP/WebSocket endpoint. The remote host still owns the environment and its work.", + boundary: "The desktop gateway owns SSH processes and password prompts. Renderer code receives a prepared environment path, not arbitrary SSH authority.", + registration: "Provisioning produces an SSH profile with its target. At connection time the gateway refreshes the bootstrap path before normal environment access continues.", + }, +} as const; + +const initial = routes.primary; +const payload = JSON.stringify(routes).replaceAll("<", "\\u003c"); +--- + +
+
+ Interactive route explorer +

Separate how an environment starts from how a client reaches it

+

Choose a route. This is a reading aid, not a live connection test: it performs no network action and has no automatic transitions.

+
+ +
+ Route to inspect +
+ {Object.entries(routes).map(([key, route], index) => ( + + ))} +
+
+ +

{initial.label}. {initial.target}.

+ +
+
{initial.target}{initial.label}
+
+
Launch transport
{initial.launch}
+
Access transport
{initial.access}
+
Trust boundary
{initial.boundary}
+
Registration fact
{initial.registration}
+
+
+ +
+

All four routes at a glance

+
+ {Object.values(routes).map((route) => ( +
+
{route.label}
+

{route.target}

+

Launch: {route.launch}

+

Access: {route.access}

+

Boundary: {route.boundary}

+
+ ))} +
+
+ + + +
+ + + + diff --git a/src/components/AcpForkLab.astro b/src/components/AcpForkLab.astro new file mode 100644 index 0000000..3bd394d --- /dev/null +++ b/src/components/AcpForkLab.astro @@ -0,0 +1,42 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("AcpForkLab requires a stable kebab-case id."); +} +const labId = `acp-fork-${id}`; + +const rows = [ + { label: "Model & mode", cursor: "Sets a base model, then resolves a mode through returned configuration/mode aliases.", grok: "Uses the setup result’s current model and calls session/set_model only if the requested model differs.", boundary: "Both call into ACP, but their selection policies are adapter code—not a generic negotiated product feature." }, + { label: "Question", cursor: "cursor/ask_question parks a Deferred and maps answers to canonical user-input events.", grok: "x.ai/ask_user_question (including an underscore variant) has its own response and cancellation mapping.", boundary: "Deferred callback waits are in-process. Durable requests exist only after later runtime ingestion." }, + { label: "Interrupt race", cursor: "Cancels ACP and resolves pending waits; prompt-in-flight counting prevents a superseded prompt from settling too early.", grok: "Marks target id before a thread lock and suppresses late notifications for interrupted turns.", boundary: "A cancel notification crosses a process boundary; neither path is a durable stop proof." }, + { label: "Rollback", cursor: "Truncates the adapter’s local read snapshot; no Cursor native revert call appears in this method.", grok: "Returns an explicit unsupported provider request error.", boundary: "Neither row is an orchestration-event rollback or a transaction with provider history." }, +]; +const payload = JSON.stringify(rows).replaceAll("<", "\\u003c"); +--- + +
+
Interactive semantic fork

One shared ACP rail, four distinct product decisions

Select a concern to compare concrete adapter behavior and the boundary it does not cross.

+
+
{rows.map((row, index) => )}
+

Selected {rows[0].label}

+

{rows[0].label}

Cursor
{rows[0].cursor}
Grok
{rows[0].grok}
Boundary
{rows[0].boundary}
+
+
All comparisons
    {rows.map((row) =>
  1. {row.label}

    Cursor: {row.cursor}

    Grok: {row.grok}

    Boundary: {row.boundary}

  2. )}
+ +
+ + diff --git a/src/components/AdapterContractLab.astro b/src/components/AdapterContractLab.astro new file mode 100644 index 0000000..0916078 --- /dev/null +++ b/src/components/AdapterContractLab.astro @@ -0,0 +1,266 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("AdapterContractLab requires a stable kebab-case id."); +} + +const stages = [ + { label: "Durable intent", short: "intent", owner: "Orchestration", boundary: "The product command has committed. No native call is part of that SQL transaction." }, + { label: "Resolve route", short: "route", owner: "ProviderService", boundary: "The persisted binding selects one configured instance and its current live adapter." }, + { label: "Invoke SPI", short: "call", owner: "ProviderAdapter", boundary: "A typed method crosses into provider-owned behavior." }, + { label: "Native runtime", short: "native", owner: "Harness", boundary: "Process, SDK query, RPC request, and native session state remain outside SQLite." }, + { label: "Canonical event", short: "event", owner: "Hot stream", boundary: "The adapter translates selected observations into ProviderRuntimeEvent values." }, + { label: "Domain update", short: "commit", owner: "Runtime ingestion", boundary: "A selected canonical event becomes durable only after an internal command commits." }, +] as const; + +const scenarios = { + start: { + label: "Start an absent session", + state: "No live adapter session", + method: "startSession(input)", + immediate: "Returns ProviderSession after native start/resume setup; this is not assistant output.", + native: "Create or adopt the provider-native session and begin its event consumer.", + event: "session.started / thread.started may follow on the hot stream.", + durable: "ProviderService can upsert the thread → instance binding and opaque cursor separately.", + caveat: "A process crash can still lose native state or an event between hot boundaries.", + tone: "success", + sourceIds: ["provider-adapter-contract", "provider-service-start-session", "provider-runtime-event-union"], + }, + send: { + label: "Send on a ready session", + state: "Live session, no active turn", + method: "sendTurn(input)", + immediate: "Returns ProviderTurnStartResult with threadId, turnId, and optional cursor—not generated text.", + native: "Submit a prompt/turn through the adapter's native transport.", + event: "turn.started, content/item activity, requests, and turn completion can arrive later.", + durable: "Runtime ingestion dispatches separate internal commands for selected events.", + caveat: "The original sequence acknowledgement proves durable intent, not native acceptance or completion.", + tone: "success", + sourceIds: ["provider-adapter-contract", "provider-turn-reactor", "provider-runtime-ingestion"], + }, + running: { + label: "Send while a turn is running", + state: "Live session with active turn", + method: "sendTurn(input) again", + immediate: "The generic SPI still exposes sendTurn; it has no steer return type or steer capability.", + native: "Concrete adapters may steer, queue, start another native turn, or reject according to their implementation.", + event: "Any accepted behavior must still be expressed through canonical runtime events.", + durable: "The durable product command does not make the provider-specific concurrency rule universal.", + caveat: "OpenCode has tested steering behavior; the ProviderAdapter contract alone does not promise it.", + tone: "warning", + sourceIds: ["provider-adapter-contract", "opencode-steer-behavior"], + }, + approve: { + label: "Resolve an approval", + state: "Pending native request", + method: "respondToRequest(threadId, requestId, decision)", + immediate: "Returns void when the adapter accepts the response operation.", + native: "Resolve the provider-native pending request or deferred handler.", + event: "request.resolved can describe the observed resolution.", + durable: "The pending/resolved product activity is durable only through ingestion commands.", + caveat: "Not every provider originates the same approval shapes or policies.", + tone: "neutral", + sourceIds: ["provider-adapter-interactions", "provider-command-control-forwarding", "provider-runtime-event-union"], + }, + input: { + label: "Answer structured input", + state: "Pending native input request", + method: "respondToUserInput(threadId, requestId, answers)", + immediate: "Returns void when the adapter accepts the answers.", + native: "Resolve an SDK deferred, ACP elicitation/extension, or native question as implemented.", + event: "user-input.resolved can describe the observed resolution.", + durable: "Request state enters the domain through separate ingestion dispatches.", + caveat: "A method in the shared interface is not proof that every native runtime can originate the request.", + tone: "neutral", + sourceIds: ["provider-adapter-interactions", "provider-runtime-event-union"], + }, + interrupt: { + label: "Interrupt an active turn", + state: "Live session with active turn", + method: "interruptTurn(threadId, turnId?)", + immediate: "Returns void after the adapter's interruption request path succeeds.", + native: "Send cancellation/interrupt through the provider-specific transport.", + event: "turn.aborted, turn.completed, warning, or error explains later observed state.", + durable: "The domain settles only when the corresponding runtime observation is ingested.", + caveat: "A successful interrupt call is not proof that no late native event can race it.", + tone: "warning", + sourceIds: ["provider-adapter-contract", "provider-command-control-forwarding", "provider-runtime-ingestion"], + }, + rollback: { + label: "Roll back provider history", + state: "Routable session or recoverable binding", + method: "rollbackThread(threadId, numTurns)", + immediate: "Returns a provider-thread snapshot when implemented successfully.", + native: "Apply the adapter's own rollback/revert semantics.", + event: "No universal canonical rollback event is guaranteed by this method.", + durable: "T3's checkpoint/revert workflow remains a separate cross-store saga.", + caveat: "Grok explicitly rejects provider rollback; Cursor and other adapters differ in what is actually reverted.", + tone: "failure", + sourceIds: ["provider-adapter-contract", "grok-rollback-unsupported", "checkpoint-revert-saga"], + }, +} as const; + +const resolved = Object.fromEntries(Object.entries(scenarios).map(([key, scenario]) => [key, { + ...scenario, + sources: scenario.sourceIds.map((sourceId) => { + const source = getSourceReference(sourceId); + return { href: sourceReferenceHref(source), label: sourceReferenceLabel(source) }; + }), +}])); +const initial = resolved.start; +const labId = `adapter-contract-${id}`; +const payload = JSON.stringify({ stages, scenarios: resolved }).replaceAll("<", "\\u003c"); +--- + +
+
+ Interactive contract tracer +

What does one adapter call actually prove?

+

Choose a call, then move from durable intent to native work and back. The return boundary and the event boundary stay visibly separate.

+
+ +
+
+ + +
+ + +
+
+ + + +

+ {initial.label}; boundary 1 of {stages.length}: {stages[0].label}. +

+ +
+
{stages[0].owner}

{stages[0].label}

{initial.method}
+

{stages[0].boundary}

+
+
Starting state
{initial.state}
+
Immediate result
{initial.immediate}
+
Native meaning
{initial.native}
+
Event lane
{initial.event}
+
Durable meaning
{initial.durable}
+
Critical caveat
{initial.caveat}
+
+
{initial.sources.map((source) => {source.label})}
+
+
+ +
+ Static adapter-operation ledger +
+ + + {Object.values(resolved).map((scenario) => )} +
CallImmediate/native meaningEvent/durable meaningCaveat
{scenario.label}
{scenario.method}
{scenario.immediate} {scenario.native}{scenario.event} {scenario.durable}{scenario.caveat}
+
+
+ + +
+ + + + diff --git a/src/components/ArtifactFactoryLab.astro b/src/components/ArtifactFactoryLab.astro new file mode 100644 index 0000000..5adf0df --- /dev/null +++ b/src/components/ArtifactFactoryLab.astro @@ -0,0 +1,167 @@ +--- +interface Props { id?: string; } +const { id = "artifact-factory" } = Astro.props; +const labId = `artifact-factory-${id}`; +const routes = { + npm: { + label: "npm CLI", + artifact: "t3 package", + boundary: "The published package contains dist only; publishing first proves the exact server version clients will invoke.", + steps: [ + ["Build server", "The server bundle emits dist/bin.mjs and the service launcher.", "Bundled code is not yet a complete product surface."], + ["Embed renderer", "The CLI build copies apps/web/dist into dist/client when it is present.", "A missing web build logs a warning during build, but publication later requires client/index.html."], + ["Assert publish inputs", "The publish command requires the executable, launcher, and bundled client entry.", "The temporary npm manifest resolves workspace/catalog dependencies before npm sees it."], + ["Publish exact version", "Release CI publishes the CLI before it is allowed to create the GitHub Release.", "The release is held if npm publication fails."], + ], + }, + desktop: { + label: "Desktop release", + artifact: "DMG · AppImage · NSIS", + boundary: "The build script describes broad platform targets, but release.yml decides which jobs actually run and ship.", + steps: [ + ["Build inputs", "Desktop, server, web, and branded client assets must exist before staging begins.", "The artifact builder validates emitted bundles rather than trusting configuration alone."], + ["Stage closure", "Electron output, server dist, resources, production dependencies, native sidecars, and platform assets form a temporary app tree.", "Windows splits the server tree into a server.asar sidecar; macOS/Linux keep one merged tree."], + ["Package per matrix", "electron-builder creates platform-specific payloads and updater metadata.", "Builder code can target more combinations than CI has elected to ship."], + ["Release four lanes", "Current CI runs macOS arm64 DMG, macOS x64 DMG, Linux x64 AppImage, and Windows x64 NSIS.", "Windows arm64 is commented out in the release matrix: capability is not a published artifact."], + ], + }, + hosted: { + label: "Hosted + mobile", + artifact: "Channel deploy · store build · OTA", + boundary: "Web channels are release-controlled aliases; mobile JavaScript can move only to native binaries with a matching fingerprint.", + steps: [ + ["Select channel", "Stable and nightly releases derive separate versions, tags, and hosted channel names.", "Vercel Git-triggered deploys are disabled so an arbitrary commit does not become a product channel."], + ["Deploy web", "Release CI builds, deploys, and aliases one immutable deployment to latest or nightly.", "The public router uses a cookie to select a channel, then rewrites the app route."], + ["Reconcile stores", "Mobile CI compares the declared app version with finished production builds and creates/submits builds when needed.", "Store approval remains an external store process, not an OTA operation."], + ["Gate OTA", "An EAS production update is published only where a completed production build matches the current native fingerprint.", "Native drift skips OTA instead of shipping JavaScript into an incompatible binary."], + ], + }, + aur: { + label: "AUR bridge", + artifact: "Arch package metadata", + boundary: "AUR repackages a published Linux AppImage; it does not build an independent desktop artifact from the source tree.", + steps: [ + ["Accept a release tag", "The release script accepts only stable semver tags or the nightly tag shape.", "Other tag shapes exit before an AUR package is changed."], + ["Choose package lane", "Stable tags select t3code-bin; nightly tags select t3code-nightly-bin.", "The package names preserve channel separation for Arch users."], + ["Pin upstream", "The script reads the named GitHub Release asset digest and the LICENSE at that tag.", "A missing or malformed SHA-256 stops packaging."], + ["Validate then publish", "namcap and makepkg validate the updated PKGBUILD before an optional authenticated AUR push.", "Without the AUR SSH key, validation completes but publication is skipped."], + ], + }, +}; +const initialRoute = "npm"; +--- + +
+
+ Interactive artifact factory · Chapter 37 +

Choose a delivery lane, then inspect its gates

+

Each lane has a different output and failure boundary. Advance manually; no state progresses on its own.

+
+
+
+ Delivery lane +
+ {Object.entries(routes).map(([key, route]) => )} +
+
+
+ +
+
+

{routes[initialRoute].label} · Gate 1 of 4

+
    + {routes[initialRoute].steps.map((step, index) =>
  1. {index + 1}{step[0]}
  2. )} +
+
+

{routes[initialRoute].label}

+

{routes[initialRoute].steps[0][0]}

+

{routes[initialRoute].steps[0][1]}

+
Output
{routes[initialRoute].artifact}
Failure boundary
{routes[initialRoute].steps[0][2]}
Lane rule
{routes[initialRoute].boundary}
+
+
+ Static artifact map +
{Object.values(routes).map((route) => )}
LaneOutputLast gate
{route.label}{route.artifact}{route.steps.at(-1)?.[0]} — {route.steps.at(-1)?.[2]}
+
+ +
+ + + + diff --git a/src/components/BookCover.astro b/src/components/BookCover.astro new file mode 100644 index 0000000..70c2e1e --- /dev/null +++ b/src/components/BookCover.astro @@ -0,0 +1,28 @@ +--- +import { Image } from "astro:assets"; +import cover from "../../cover.png"; +import lock from "../../sources/t3code.lock.json"; +const base = import.meta.env.BASE_URL.endsWith("/") ? import.meta.env.BASE_URL : `${import.meta.env.BASE_URL}/`; +--- + +
+
+
+ T3 Code Decoded book cover: an octopus connecting Codex, Claude Code, Cursor, Grok, OpenCode, and tools +
+
+ Source-level field guide +

Follow the control plane all the way down.

+

From a tap on a phone to a provider subprocess, persisted event, hidden Git checkpoint, and streamed UI update—every layer is explained against one pinned source revision.

+ +
+ pingdotgg/t3code · commit {lock.shortCommit} + Local/hosted web · Electron · iOS/Android + Codex · Claude · Cursor · Grok · OpenCode +
+
+
+
diff --git a/src/components/Callout.astro b/src/components/Callout.astro new file mode 100644 index 0000000..0405a3e --- /dev/null +++ b/src/components/Callout.astro @@ -0,0 +1,13 @@ +--- +interface Props { + title: string; + tone?: "info" | "warning" | "success"; +} +const { title, tone = "info" } = Astro.props; +--- + + + diff --git a/src/components/CheckpointGraphLab.astro b/src/components/CheckpointGraphLab.astro new file mode 100644 index 0000000..24cf096 --- /dev/null +++ b/src/components/CheckpointGraphLab.astro @@ -0,0 +1,135 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("CheckpointGraphLab requires a stable kebab-case id."); +} +const labId = `checkpoint-graph-${id}`; +const states = [ + { + id: "before", + label: "Before turn", + eyebrow: "Baseline · turn 0", + detail: "The current workspace is captured as the baseline hidden ref. The branch still points at its ordinary commit; the checkpoint is a separate content snapshot.", + ref: "refs/t3/checkpoints//turn/0", + files: ["README.md · unchanged", "src/app.ts · unchanged"], + consequence: "A later turn diff can compare this baseline to the next checkpoint.", + }, + { + id: "after", + label: "After turn", + eyebrow: "Checkpoint · turn 1", + detail: "After the turn, T3 builds a tree with an isolated Git index, stores it under a hidden ref, then derives a changed-file summary before it records checkpoint metadata.", + ref: "refs/t3/checkpoints//turn/1", + files: ["README.md · 3 additions, 1 deletion", "src/app.ts · 12 additions"], + consequence: "The visible summary is derived from the checkpoint diff; it is not an independent file watcher.", + }, + { + id: "diff", + label: "Inspect a diff", + eyebrow: "Read-only comparison", + detail: "A turn view compares checkpoint 0 → 1. A full-thread view compares the baseline → a selected checkpoint. Working-tree and branch views are separate live Git comparisons.", + ref: "turn 0 → turn 1", + files: ["- const title = \"old\";", "+ const title = \"new\";", "+ export const ready = true;"], + consequence: "Inspecting a patch does not restore files or alter the provider conversation.", + }, + { + id: "revert", + label: "Revert to turn 0", + eyebrow: "Ordered destructive saga", + detail: "The reactor restores worktree and index content, cleans untracked paths, refreshes workspace entries, asks the bound provider to roll back counted turns, attempts best-effort deletion of newer hidden refs, then records a completed revert.", + ref: "restore turn 0; prune turn 1", + files: ["README.md · baseline restored", "src/app.ts · baseline restored", "turn 1 hidden ref · delete attempted"], + consequence: "This is a content restore plus a provider-history operation, not a Git branch reset or an undo of a remote push.", + }, + { + id: "failure", + label: "Provider rollback fails", + eyebrow: "Partial failure boundary", + detail: "Filesystem restore happens before provider rollback. If the live provider cannot roll back, the reactor appends a failure activity and does not dispatch thread.reverted; the working tree may already be restored while durable history and stale refs remain.", + ref: "filesystem restored; completion withheld", + files: ["README.md · baseline restored", "provider conversation · not rolled back", "turn 1 ref · still present"], + consequence: "The user must treat this as a mismatched partial state, not as a completed revert.", + }, +] as const; +const payload = JSON.stringify(states).replaceAll("<", "\\u003c"); +--- + +
+
+ Interactive checkpoint graph +

Walk one turn through capture, review, and a partial rollback failure

+

Each button is a discrete state. Nothing plays by itself, and the full ledger stays available without JavaScript.

+
+
+ {states.map((state, index) => )} +
+

State: {states[0].label}. {states[0].detail}

+
+ +
+ {states[0].eyebrow} +

{states[0].label}

+

{states[0].detail}

+
+
Reference / operation
{states[0].ref}
+
Observed files
    {states[0].files.map((file) =>
  • {file}
  • )}
+
Boundary
{states[0].consequence}
+
+
+
+
+ Complete state ledger +
    + {states.map((state) =>
  1. {state.label}

    {state.detail}

    Boundary: {state.consequence}

  2. )} +
+
+ + +
+ + + + diff --git a/src/components/ClaudeSdkStreamLab.astro b/src/components/ClaudeSdkStreamLab.astro new file mode 100644 index 0000000..530171c --- /dev/null +++ b/src/components/ClaudeSdkStreamLab.astro @@ -0,0 +1,47 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ClaudeSdkStreamLab requires a stable kebab-case id."); +} +const labId = `claude-sdk-${id}`; + +const messages = [ + { label: "Query configured", native: "The SDK query receives cwd, model, effort, permission mode, and optional resume metadata.", product: "A ProviderSession records a live Claude binding and a resumable cursor shape.", caveat: "The SDK session and query stream are provider-owned runtime state; a stored cursor is not a replay of every transient message." }, + { label: "Assistant + tool", native: "Assistant text and tool-use/result messages stream from the Agent SDK.", product: "Content and item lifecycle events are normalized for thread projections.", caveat: "The canonical item taxonomy is T3’s contract; it is not an assertion that all SDK message fields persist." }, + { label: "Permission / question", native: "A tool request or structured input pauses on an SDK-side deferred response.", product: "request.opened or user-input.requested gives clients a canonical action.", caveat: "The deferred is volatile. The durable record appears only after runtime ingestion’s internal command commits." }, + { label: "Todo / task", native: "TodoWrite and agent/task-shaped SDK messages provide planning and work signals.", product: "turn.plan.updated and task/activity events drive product work views.", caveat: "These are adapter normalizations, not a cross-provider task scheduler or durable execution queue." }, + { label: "Result / error", native: "A terminal SDK result carries success, cancellation, error, and sometimes usage fields.", product: "turn completion plus optional thread token usage or runtime error reaches T3.", caveat: "Live context telemetry is not transcript accounting, and an SDK result still crosses a hot delivery bridge before durable projection." }, +]; +const payload = JSON.stringify(messages).replaceAll("<", "\\u003c"); +--- + +
+
Interactive stream classifier

Classify one Claude SDK observation

Choose an event family to see the native message, its product projection, and the point where durable truth begins.

+
+
{messages.map((message, index) => )}
+

Selected {messages[0].label}

+

{messages[0].label}

Native SDK meaning
{messages[0].native}
Canonical product meaning
{messages[0].product}
Boundary to keep honest
{messages[0].caveat}
+
+
All message families
    {messages.map((message) =>
  1. {message.label}

    {message.native}

    {message.product}

    {message.caveat}

  2. )}
+ + +
+ + + + diff --git a/src/components/ClientConvergenceLab.astro b/src/components/ClientConvergenceLab.astro new file mode 100644 index 0000000..ced79da --- /dev/null +++ b/src/components/ClientConvergenceLab.astro @@ -0,0 +1,162 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +--- + +
+
+ Interactive convergence lab +

Reject what cannot still be true

+

Advance one race at a time. The first render is a still, authoritative snapshot at sequence 10.

+
+ +
+ + + + + + + +
+ +

+ Snapshot at sequence 10 is loaded. No page request is in flight. +

+ +
+
SessionA
+
Live cursor10
+
History epoch0
+
Older pageidle
+
+ +
    +
  1. Snapshotauthoritative window: turns 8–10
  2. +
+ +
+ Static race reference +
    +
  • A snapshot replaces loaded history and establishes its cursor.
  • +
  • An event at or below that cursor is ignored as overlap or a duplicate.
  • +
  • An invalid or oversized resume gap receives a new snapshot, not a partial replay.
  • +
  • A new session refreshes authority before reusing a cursor.
  • +
  • A revert increments history epoch, so a pre-revert older page is discarded.
  • +
  • An older page ahead of live cursor waits for its watermark; a stale page does not merge.
  • +
+
+ +
+ + + + diff --git a/src/components/CodexRpcBoundaryLab.astro b/src/components/CodexRpcBoundaryLab.astro new file mode 100644 index 0000000..84035f9 --- /dev/null +++ b/src/components/CodexRpcBoundaryLab.astro @@ -0,0 +1,63 @@ +--- +interface Props { id: string; } +interface Step { label: string; native: string; canonical: string; durable: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("CodexRpcBoundaryLab requires a stable kebab-case id."); +} +const labId = `codex-rpc-${id}`; + +const steps: Step[] = [ + { label: "Start / resume", native: "Spawn codex app-server, initialize it, then start or resume a provider thread.", canonical: "session.started and thread.started identify a live adapter session.", durable: "Only the orchestration binding and any saved resume cursor can survive; the child process and event consumer are live state." }, + { label: "Turn request", native: "turn/start carries the prompt plus selected model, reasoning effort, and service tier.", canonical: "turn.started and item/content events describe the product-visible turn.", durable: "The earlier turn-start command is durable intent. Native request completion is not a SQL commit." }, + { label: "Server asks", native: "The app-server sends an incoming approval or user-input JSON-RPC request.", canonical: "request.opened or user-input.requested becomes a pending product request.", durable: "The pending native handler waits in process; its durable counterpart arrives only after runtime ingestion dispatches an internal command." }, + { label: "Notifications", native: "Items, plan deltas, token usage, reroutes, and errors arrive as app-server notifications.", canonical: "The adapter maps selected shapes into ProviderRuntimeEvent values.", durable: "The adapter queue and hot provider stream are volatile until ingestion commits a derived internal command." }, + { label: "Stop / failure", native: "Close the runtime or observe child stdio/process/protocol failure.", canonical: "session.exited, runtime.warning, or runtime.error explains the observed outcome.", durable: "Stopping a process does not retroactively prove a provider result was projected; a prior accepted intent may outlive delivery." }, +]; +const payload = JSON.stringify(steps).replaceAll("<", "\\u003c"); +--- + +
+
Interactive transport ledger

Move one Codex observation across the boundary

The labels deliberately separate upstream JSON-RPC from T3’s stable runtime vocabulary and from durable orchestration state.

+
+
+ + + +
+

Position 1 of {steps.length}: {steps[0].label}

+

{steps[0].label}

Native app-server
{steps[0].native}
Canonical T3 event
{steps[0].canonical}
Durability boundary
{steps[0].durable}
+
+
All boundary positions
    {steps.map((step) =>
  1. {step.label}

    Native: {step.native}

    Canonical: {step.canonical}

    Durable: {step.durable}

  2. )}
+ + +
+ + + + diff --git a/src/components/CommandBoundaryLab.astro b/src/components/CommandBoundaryLab.astro new file mode 100644 index 0000000..87ff9f7 --- /dev/null +++ b/src/components/CommandBoundaryLab.astro @@ -0,0 +1,664 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { + id: string; +} + +interface BoundaryStage { + label: string; + shortLabel: string; + position: string; + durable: string; + external: string; + client: string; + retry: string; + provider: string; + guarantee: string; + tone: "neutral" | "warning" | "failure" | "success"; + sourceIds: string[]; +} + +interface BoundaryPath { + label: string; + description: string; + stages: BoundaryStage[]; +} + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("CommandBoundaryLab requires a stable kebab-case id."); +} + +const paths: Record<"existing" | "bootstrap", BoundaryPath> = { + existing: { + label: "Turn on an existing thread", + description: + "One normalized command is decided, then its two-to-four-event batch, projections, and accepted receipt share one SQL transaction.", + stages: [ + { + label: "Before normalization", + shortLabel: "wire", + position: "The client command has crossed schema and authorization checks, but normalization has not produced the dispatchable command.", + durable: "No orchestration event or command receipt exists.", + external: "No attachment staging or provider work has begun.", + client: "The request can fail without a durable orchestration result.", + retry: "The same command id enters the normal path again because there is no receipt to find.", + provider: "No provider intent exists.", + guarantee: "No durable intent", + tone: "neutral", + sourceIds: ["command-union-boundary", "normalizer-staging-boundary"], + }, + { + label: "After normalization and staging", + shortLabel: "stage", + position: "The server has supplied timestamps and workspace context and may have created attachment directories or written attachment bytes.", + durable: "The event store and receipt table are still unchanged.", + external: "Filesystem staging can already exist outside the later SQL transaction.", + client: "A later failure returns an error even though staged files may remain.", + retry: "The command is normalized and staged again; receipt deduplication has not started yet.", + provider: "No provider intent exists.", + guarantee: "External work, no receipt", + tone: "warning", + sourceIds: ["normalizer-staging-boundary", "turn-normalizer"], + }, + { + label: "Invariant rejection", + shortLabel: "reject", + position: "The serialized decider has read the authoritative in-memory model and refuses the command before opening the SQL transaction.", + durable: "No event is appended. A rejected receipt is attempted afterward on a best-effort path.", + external: "Any earlier normalization-time staging is outside that rejection bookkeeping.", + client: "The caller receives an invariant error.", + retry: "After client normalization runs again, a saved rejected receipt keeps the same id rejected without re-evaluation; if that receipt was not saved, the command can be decided again.", + provider: "No provider intent is published.", + guarantee: "Best-effort sticky rejection", + tone: "failure", + sourceIds: ["existing-turn-decider", "engine-rejected-receipt"], + }, + { + label: "SQL transaction failure", + shortLabel: "rollback", + position: "Decision has already allocated event data, but an event append, projection, or receipt write fails inside the transaction.", + durable: "Events, transactional projections, and the accepted receipt roll back together.", + external: "Pre-transaction staged files are not part of the SQL rollback.", + client: "The caller receives a persistence failure; no sequence is acknowledged.", + retry: "With no accepted receipt, the same id is normalized and decided again; clock and UUID-derived values may differ.", + provider: "No committed event reaches the hot event bus.", + guarantee: "SQL all-or-none", + tone: "failure", + sourceIds: ["decider-effect-dependencies", "engine-commit-publication"], + }, + { + label: "Hard crash after commit", + shortLabel: "gap", + position: "The SQL transaction committed, but the process dies before the in-memory fold and PubSub loop can publish the batch.", + durable: "The complete event batch, projections, and accepted receipt are durable.", + external: "The hot reactor saw none of this batch in the failed process.", + client: "No acknowledgement reaches the caller.", + retry: "After any client normalization work, a same-id retry returns the stored last sequence and does not republish the missing hot events.", + provider: "Durable turn intent can exist without the provider reactor receiving its trigger.", + guarantee: "Durable but not delivered", + tone: "failure", + sourceIds: ["engine-commit-publication", "command-receipt-handling", "engine-failure-reconciliation", "hot-reactor-no-replay"], + }, + { + label: "Sequence acknowledged", + shortLabel: "ack", + position: "The engine committed the batch, updated its in-memory model, and offered every committed event to the hot PubSub before returning.", + durable: "Two to four events, their synchronous projections, and one accepted receipt are committed.", + external: "Publication wakes asynchronous reactors; provider execution is outside this transaction.", + client: "The RPC result contains the last committed event sequence.", + retry: "The same id and aggregate return that stored sequence without deciding or appending again.", + provider: "The acknowledgement proves durable intent, not that a harness accepted, ran, or completed the turn.", + guarantee: "Durable intent acknowledged", + tone: "success", + sourceIds: ["turn-atomic-batch", "command-commit-acknowledgement", "provider-turn-reactor"], + }, + ], + }, + bootstrap: { + label: "Full first-turn WebSocket bootstrap", + description: + "The full WebSocket path creates a thread, prepares a worktree, launches setup, and starts the turn through separate durability boundaries.", + stages: [ + { + label: "After normalization, before the saga", + shortLabel: "stage", + position: "The WebSocket turn-start command still carries its bootstrap payload after normalization; the ordinary command engine has not received a subcommand.", + durable: "No bootstrap step has committed.", + external: "Attachment staging may already exist, but no worktree or setup process has been requested.", + client: "The WebSocket request can still fail without creating the thread.", + retry: "The same outer id has no saga-level receipt that can replay the whole result.", + provider: "No provider intent exists.", + guarantee: "No saga-level idempotency", + tone: "neutral", + sourceIds: ["command-union-boundary", "bootstrap-saga-full"], + }, + { + label: "Thread creation committed", + shortLabel: "thread", + position: "A server-generated id dispatched thread.create through the ordinary engine as the first saga step.", + durable: "The thread event and that subcommand's receipt are committed independently of the final turn.", + external: "No worktree is guaranteed yet.", + client: "The outer request is still pending.", + retry: "Repeating the outer request tries the creation path again; it does not retrieve one receipt for the whole saga.", + provider: "The thread exists, but no turn-start request has been committed.", + guarantee: "First independent commit", + tone: "warning", + sourceIds: ["bootstrap-saga-full", "bootstrap-command-path"], + }, + { + label: "Worktree prepared and metadata committed", + shortLabel: "Git + meta", + position: "Git remote/worktree operations run outside SQLite, then thread.meta.update commits with another server-generated id.", + durable: "Thread metadata can point at the newly prepared worktree in a separate event and receipt.", + external: "A branch and worktree now exist outside the event-store transaction.", + client: "The outer request remains pending and can still fail later.", + retry: "An identical outer retry can collide with already-created thread, branch, or worktree state.", + provider: "No final turn intent is guaranteed yet.", + guarantee: "Mixed durable and Git state", + tone: "warning", + sourceIds: ["bootstrap-saga-full"], + }, + { + label: "Setup launch fails", + shortLabel: "setup", + position: "The setup runner rejects the launch. The handler attempts to append failure activity, logs a warning, and continues the saga.", + durable: "Failure activity is best effort; the earlier thread and metadata commits remain.", + external: "No setup process started, but the prepared worktree remains.", + client: "Setup-launch failure alone does not fail the outer turn-start request.", + retry: "The saga continues to the final turn; this is not a rollback boundary.", + provider: "The eventual provider turn may run against a worktree whose setup did not launch.", + guarantee: "Recorded warning, saga continues", + tone: "warning", + sourceIds: ["bootstrap-saga-full"], + }, + { + label: "Final turn fails; compensate", + shortLabel: "delete", + position: "A non-interruption failure reaches compensation after the thread was created, so thread.delete is dispatched uninterruptibly.", + durable: "Successful compensation tombstones the thread in another independent commit; prior history is not erased.", + external: "The Git worktree and branch are not removed by this compensation.", + client: "The caller receives the original dispatch failure, annotated as deleted only when cleanup succeeds.", + retry: "Retrying the outer request is a new saga attempt, not a replay of an atomic transaction.", + provider: "No successful final turn acknowledgement exists.", + guarantee: "Domain compensation only", + tone: "failure", + sourceIds: ["bootstrap-saga-full", "bootstrap-command-path"], + }, + { + label: "Final turn acknowledged", + shortLabel: "ack", + position: "The last saga step strips bootstrap data and dispatches the normalized turn-start through the ordinary engine.", + durable: "Earlier saga commits plus the final two-to-four-event turn transaction are durable, each with its own receipt boundary.", + external: "Git/setup effects remain outside SQL and provider work begins asynchronously from hot events.", + client: "The WebSocket RPC returns the final turn transaction's last sequence.", + retry: "The outer bootstrap is not end-to-end idempotent even though each dispatched subcommand has receipt semantics.", + provider: "The acknowledgement proves durable turn intent only.", + guarantee: "Successful saga, not one transaction", + tone: "success", + sourceIds: ["bootstrap-saga-full", "turn-atomic-batch", "provider-turn-reactor"], + }, + ], + }, +}; + +const resolvedPaths = Object.fromEntries( + Object.entries(paths).map(([key, path]) => [ + key, + { + ...path, + stages: path.stages.map(({ sourceIds, ...stage }) => ({ + ...stage, + sources: sourceIds.map((sourceId) => { + const source = getSourceReference(sourceId); + return { + label: sourceReferenceLabel(source), + href: sourceReferenceHref(source), + }; + }), + })), + }, + ]), +); +const initial = resolvedPaths.existing.stages[0]; +const payload = JSON.stringify(resolvedPaths).replaceAll("<", "\\u003c"); +const labId = `command-boundary-${id}`; +--- + +
+
+ Interactive boundary explorer +

Where can a command fail?

+

Switch paths and move the failure position. Watch which state is durable, which state is external, and what an identical retry can actually recover.

+
+ +
+ + +
+ + +
+
+ +

{resolvedPaths.existing.description}

+ + + + +

+ Existing-thread path, position 1 of 6: {initial.label}. {initial.guarantee}. +

+ +
+
+
Position 1 of 6

{initial.label}

+ {initial.guarantee} +
+

{initial.position}

+
+
Durable state
{initial.durable}
+
External state
{initial.external}
+
Client sees
{initial.client}
+
Identical retry
{initial.retry}
+
Provider implication
{initial.provider}
+
+
+ {initial.sources.map((source) => {source.label})} +
+
+ +
+ Static boundary ledger + {Object.entries(resolvedPaths).map(([, path]) => ( +
+

{path.label}

+

{path.description}

+
+ + + + {path.stages.map((stage, index) => ( + + + + + + ))} + +
PositionDurable / external stateRetry and provider meaning
{index + 1}. {stage.label}{stage.durable} {stage.external}{stage.retry} {stage.provider}
+
+
+ ))} +
+ + +
+ + + + diff --git a/src/components/ConnectPlaneLab.astro b/src/components/ConnectPlaneLab.astro new file mode 100644 index 0000000..394a22e --- /dev/null +++ b/src/components/ConnectPlaneLab.astro @@ -0,0 +1,116 @@ +--- +interface Props { id: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ConnectPlaneLab requires a stable kebab-case id."); +} +const labId = `connect-plane-${id}`; +--- + +
+
+ Interactive credential ladder · Chapter 35 +

Launch the connection, then move the work on a different path

+

Choose a manual step. The lab distinguishes the short setup exchange from the HTTP and WebSocket traffic that follows it.

+
+ +
+
+ + +
+ + +
+
+ +
+

Control plane · account and endpoint authorization

+

Clerk session reaches the relay

+

A signed-in client presents its Clerk credential to list or link environments. This authorizes relay control-plane work; it is not an environment WebSocket credential.

+
+
Sender → receiver
Client → relay
+
Proof in use
Clerk bearer credential
+
What becomes possible
Discovery, link challenge, or relay DPoP token exchange
+
+ +
+

Step 1 of 6. Control plane.

+
+ + +
+ Static credential ladder and plane boundary +
+ + + + + + + + + + +
StepPathCredential or proofResult
1Client → relayClerk bearer credentialAccount-scoped relay operations
2Client → relayDevice P-256 DPoP proof; relay issues DPoP-bound access tokenProof-bound relay request authority
3Relay → managed environmentRelay-signed short-lived mint request, bound to the client key thumbprintEnvironment bootstrap credential returned through the brokered connection flow
4Client → managed environmentBootstrap credential plus DPoP proofEnvironment DPoP access token
5Client → managed environmentEnvironment DPoP access token plus fresh proofWebSocket ticket
6Client ↔ managed environmentTicketed WebSocket and direct API authorizationNormal T3 HTTP and WebSocket traffic; it does not traverse the relay
+
+
+
+ + + + diff --git a/src/components/ContextOwnershipLab.astro b/src/components/ContextOwnershipLab.astro new file mode 100644 index 0000000..f8702f6 --- /dev/null +++ b/src/components/ContextOwnershipLab.astro @@ -0,0 +1,268 @@ +--- +interface Props { id: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ContextOwnershipLab requires a stable kebab-case id."); +} +const labId = `context-ownership-${id}`; +--- + +
+
+ Interactive ownership ledger +

Ask what survives before calling it memory

+

Select a teaching event. The ledger identifies authority, durable records, and the narrow recovery claim; it never simulates a model or invents a provider prompt.

+
+ +
+ + + + + +
+ +
+
+

Event 1 of 5 · live provider work begins

+

A provider receives a turn in its own native session

+

T3 constructs the visible current-turn payload. The provider-native session owns the accumulated conversation context and private compaction state.

+
+ +
+ + + + + + + + + +
RecordAuthoritative ownerThis eventAfter server restart
Accumulated native contextprovider-native sessionT3's explicit request enters provider-owned historyprovider-specific resume only
T3 thread historyT3 orchestrationmessage/activity projection may commitdurable product record reloads
Resume cursorprovider shape; T3 persists bindingadapter may return/update itsame adapter receives opaque cursor
Context telemetryprovider emits; T3 latest-selectsonly if a usable event arriveslatest retained activity may render
Client cache/draft/outboxclient surfacesurface-specific local statenot a provider prompt or server authority
+
+ +
+ Boundary statement +

T3 constructs and records the visible request around a turn. It does not own or serialize the provider's accumulated hidden conversation context.

+
+ +
+ context-current-turn-payloadprovider-session-contract +
+
+ +

Selected event: Send a turn.

+ + +
+ Static ownership and restart reference +
+ + + + + + + + + + +
QuestionAnswer at the pinned revision
Who owns exact model prompt context?T3 constructs the visible current-turn request; the selected provider's native session owns accumulated conversation context and hidden provider state.
What does T3 persist to attempt continuation?A provider/instance-bound runtime record with an opaque resume cursor, runtime/session metadata, plus separate thread projections.
What does compaction add to T3?A normalized context-compaction activity when an adapter reports a compacted provider thread; no generic T3 summary/prompt replacement is established.
What is the context meter?The newest valid provider-reported context-window activity available in the bounded thread snapshot, not a prompt archive, aggregate usage total, or cost ledger.
Is there universal long-term memory?No such cross-provider T3 subsystem is established by the inspected generic contracts/service paths. This is an audited inference, not a claim about native provider features.
What about local drafts/outbox/cache?Client-owned resilience/presentation state. It is deliberately deferred to Chapter 33 and cannot replace provider-session recovery.
+
+
+
+ + + + diff --git a/src/components/DecisionGrid.astro b/src/components/DecisionGrid.astro new file mode 100644 index 0000000..6cc393b --- /dev/null +++ b/src/components/DecisionGrid.astro @@ -0,0 +1,16 @@ +--- +interface Decision { label: string; title: string; text: string; } +interface Props { items: Decision[]; } +const { items } = Astro.props; +--- + +
+ {items.map((item) => ( +
+ {item.label} +

{item.title}

+

{item.text}

+
+ ))} +
+ diff --git a/src/components/DecisionLedgerLab.astro b/src/components/DecisionLedgerLab.astro new file mode 100644 index 0000000..d5d88a9 --- /dev/null +++ b/src/components/DecisionLedgerLab.astro @@ -0,0 +1,352 @@ +--- +interface Props { + id?: string; +} + +const { id = "architecture-decision-ledger" } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("DecisionLedgerLab requires a stable kebab-case id."); +} + +const decisions = [ + { + category: "domain", + classification: "Shipped", + title: "Server authority", + pressure: "Remote clients must control one workspace without becoming competing owners of provider processes, Git, terminals, or files.", + choice: "One environment server owns product authority; clients use authenticated RPC and projections.", + benefit: "Authorization, orchestration, workspace effects, and durable product history meet at one address.", + cost: "Availability and recovery depend on that environment; clients reconcile rather than write authoritatively.", + alternative: "Client-owned or peer-to-peer workspaces with a separate conflict and credential model.", + trigger: "Concurrent offline editing or multi-writer workspace authority becomes a core requirement.", + }, + { + category: "domain", + classification: "Shipped", + title: "Transactional event core", + pressure: "A command needs a durable acceptance boundary and a retry answer before external work completes.", + choice: "Decide, append events, fold projections, and write a receipt in one SQLite transaction.", + benefit: "Accepted intent and its receipt survive together; failed transactions leave no acceptance result.", + cost: "Files, provider calls, and later delivery remain outside the transaction; projections require maintenance.", + alternative: "Direct CRUD where replayable history and independently shaped read models are not valuable.", + trigger: "Immutable command history and projection diversity stop paying for their operational complexity.", + }, + { + category: "delivery", + classification: "Shipped", + title: "Hot post-commit reactors", + pressure: "Do not call a harness while the domain transaction could still roll back.", + choice: "Publish committed events to scoped, hot reactor workers; keep failures isolated from acceptance.", + benefit: "Rollback cannot have caused provider work, and one consumer failure does not undo durable history.", + cost: "A crash after commit can lose pending observation; sends and runtime ingestion are not a durable outbox.", + alternative: "Durable outbox with attempts, idempotency keys, and a policy for ambiguous external acceptance.", + trigger: "An accepted turn must eventually imply an attempted provider send across process loss.", + }, + { + category: "delivery", + classification: "Shipped", + title: "Snapshot + cursor", + pressure: "Clients need rebuildable read state and bounded resume without calling every page one global snapshot.", + choice: "Each projection advances its own cursor; composed snapshots use a safe watermark and subscriptions repair gaps.", + benefit: "Read models evolve independently and can rebuild from committed events.", + cost: "Several watermarks, order-sensitive projectors, replay limits, and client race guards must remain intelligible.", + alternative: "One authoritative document per thread with fewer projections and less independent fan-out.", + trigger: "Projection lag, cross-view joins, or replay operations exceed the current cursor model's operating envelope.", + }, + { + category: "integration", + classification: "Shipped", + title: "Provider adapters", + pressure: "Harnesses disagree about sessions, approvals, streams, context, and process ownership.", + choice: "A narrow adapter contract emits canonical runtime facts while ProviderService owns product policy and routing.", + benefit: "One product model preserves native provenance without inventing false provider parity.", + cost: "Adapter maintenance and capability differences remain explicit; no universal conformance proof exists.", + alternative: "A stricter generic protocol that may discard native features or push product policy into every driver.", + trigger: "Important native lifecycles require pervasive escape hatches that the canonical contract cannot express.", + }, + { + category: "connectivity", + classification: "Shipped", + title: "One reconnect owner", + pressure: "Several views and devices can observe an environment without independent retry loops or merged authorities.", + choice: "An environment-scoped supervisor owns generations and one active lease; caches synchronize separately.", + benefit: "Transport lifecycle has one owner while shell and thread views keep precise refresh boundaries.", + cost: "Leases, generations, and surface-specific reconciliation add client-runtime complexity.", + alternative: "A global connection manager that would need another way to preserve environment ownership.", + trigger: "The product adds a real cross-environment write model, not just combined presentation.", + }, + { + category: "connectivity", + classification: "Shipped", + title: "Durable mobile intent outbox", + pressure: "A user can send while the phone loses connectivity or foreground time.", + choice: "Optimistically enqueue, persist durably, then confirm and deliver through a serialized mobile outbox.", + benefit: "User intent can survive locally before the environment can accept it.", + cost: "Backoff, existence guards, confirmation, and delivery choices become a separate lifecycle.", + alternative: "Always-online direct send, sacrificing the local recovery contract.", + trigger: "Intent becomes multi-device collaborative work needing server-issued identities or all clients need the same queue.", + }, + { + category: "operations", + classification: "Shipped", + title: "Exact-version updates", + pressure: "A visible client must not request a server runtime that is unavailable or incompatible.", + choice: "Publish the exact CLI first; stage and preflight the exact server runtime before launcher activation.", + benefit: "An update target is reproducible and the managed-server trial has a defined rollback boundary.", + cost: "Release order, launcher compatibility, and platform-specific update state machines remain necessary.", + alternative: "Floating channel updates paired with a stronger compatibility negotiation protocol.", + trigger: "Compatibility proof becomes sufficient without requiring equal client and server versions.", + }, + { + category: "connectivity", + classification: "Shipped", + title: "Scope-driven background work", + pressure: "Mobile should remain useful in the background without keeping every environment permanently active.", + choice: "Reference-counted scopes retain declared per-environment background demand.", + benefit: "Continuation has an owner and can end when that owner releases its interest.", + cost: "Scope cleanup and platform scheduling constraints remain part of correctness; it is not a durable job queue.", + alternative: "An always-on global worker with higher resource use and leak risk.", + trigger: "The product needs OS-managed durable jobs with explicit completion receipts.", + }, +]; + +const payload = JSON.stringify(decisions).replaceAll("<", "\\u003c"); +const first = decisions[0]; +--- + +
+
+ Interactive decision ledger +

Trace the trade-off, then test its reversal trigger

+

Filter the ledger, select a decision, and move through its six-step path. No animation advances on its own.

+
+ +
+
+ Category +
+ + + + + + +
+
+ +
+ + +
+
+

{first.classification} {first.category}

+

{first.title}

+
+
    +
  1. 1Pressure

    {first.pressure}

  2. +
  3. 2Choice

    {first.choice}

  4. +
  5. 3Benefit

    {first.benefit}

  6. +
  7. 4Cost

    {first.cost}

  8. +
  9. 5Alternative

    {first.alternative}

  10. +
  11. 6Reversal trigger

    {first.trigger}

  12. +
+
+ +

1 of 6 · Pressure

+ +
+
+
+

+ Server authority selected. Step 1 of 6: Pressure. +

+
+ +
+ Complete static ledger +
+ + + + {decisions.map((decision) => ( + + + + + + + + + + ))} + +
DecisionPressureChoiceBenefitCostAlternativeReversal trigger
{decision.classification}{decision.title}{decision.pressure}{decision.choice}{decision.benefit}{decision.cost}{decision.alternative}{decision.trigger}
+
+
+ + +
+ + + + diff --git a/src/components/DeliveryGapLab.astro b/src/components/DeliveryGapLab.astro new file mode 100644 index 0000000..d18bcfb --- /dev/null +++ b/src/components/DeliveryGapLab.astro @@ -0,0 +1,357 @@ +--- +import { + getSourceReference, + sourceReferenceHref, + sourceReferenceLabel, +} from "../lib/sources"; + +interface Props { + id?: string; +} + +const { id = "post-commit-delivery-gap" } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("DeliveryGapLab requires a stable kebab-case id."); +} + +const phases = [ + { + label: "Before commit", + boundary: "The SQL transaction has not committed.", + durable: "No accepted intent is durable yet.", + volatile: "Only the command worker and transaction-local writes exist.", + external: "No provider work has started.", + retry: "After restart, the client can retry and the command can execute normally.", + sourceId: "engine-receipt-publication-boundary", + }, + { + label: "Transaction open", + boundary: "Events, projections, and the accepted receipt have been written inside one SQL transaction.", + durable: "A process crash rolls the uncommitted transaction back as a unit.", + volatile: "The proposed in-memory command model has not replaced the live model.", + external: "The event has not reached the hot bus.", + retry: "No accepted receipt survives, so the retry can decide and commit again.", + sourceId: "engine-receipt-publication-boundary", + }, + { + label: "Commit returned", + boundary: "The event, SQL projections, and accepted receipt are durable; publication has not happened yet.", + durable: "Intent and its command sequence survive restart.", + volatile: "No durable outbox row or per-reactor cursor records pending delivery.", + external: "The provider has not seen the intent.", + retry: "The same command id returns the stored sequence and does not republish, so that retry leaves this delivery gap unrepaired.", + sourceId: "engine-receipt-publication-boundary", + }, + { + label: "Hot publish", + boundary: "The committed event is offered to current PubSub subscribers.", + durable: "The domain event remains durable in SQLite.", + volatile: "Subscriber queues live only in this process; publication is not a recoverable job record.", + external: "A reactor may or may not have dequeued the event.", + retry: "A receipt hit still returns success without replaying reactor work.", + sourceId: "provider-reactor-hot-subscription", + }, + { + label: "Turn-start observed", + boundary: "For a turn-start event, the provider reactor handles the event and marks its derived turn key in a volatile dedupe cache.", + durable: "The original intent is durable, but reactor progress is not.", + volatile: "The dedupe mark is made before the provider effect and disappears on restart.", + external: "The adapter call has not necessarily begun.", + retry: "Within the same process a duplicate can be suppressed even after a later failure; after restart the hot event itself is gone.", + sourceId: "provider-reactor-forked-send", + }, + { + label: "Send forked", + boundary: "The serialized handler forks providerService.sendTurn and can return to its queue.", + durable: "There is still no durable side-effect attempt record.", + volatile: "The child fiber is outside the worker's outstanding counter.", + external: "Two provider sends can overlap even though handler bodies were dequeued serially.", + retry: "Closing the scope may interrupt the child; the worker drain does not prove that the send completed.", + sourceId: "provider-reactor-forked-send", + }, + { + label: "Provider accepted", + boundary: "The external harness may have accepted the turn before local binding/state persistence finishes.", + durable: "The original intent survives, but acceptance by the harness is outside SQLite's transaction.", + volatile: "Local knowledge of the provider result may still be only in a running fiber.", + external: "The turn can continue in the harness after the server loses its exact completion point.", + retry: "Recovery is ambiguous: blindly repeating can duplicate work, while doing nothing can strand it.", + sourceId: "provider-send-binding-order", + }, + { + label: "Runtime publish", + boundary: "ProviderService logs a canonical runtime event and then publishes it to another hot PubSub.", + durable: "The diagnostic log is best-effort and is not the orchestration recovery ledger.", + volatile: "Runtime ingestion has not necessarily consumed the event.", + external: "The harness action has occurred; its canonical result is in transit inside the process.", + retry: "A crash before ingestion loses this delivery; no durable runtime-event cursor replays it.", + sourceId: "provider-runtime-publish", + }, + { + label: "Buffer released", + boundary: "Runtime ingestion invalidates a buffered entry before dispatching its internal command.", + durable: "No new orchestration result is durable until that internal command commits.", + volatile: "Dispatch interruption or failure can lose the released batch; the removed value is not restored on this path.", + external: "The provider result already exists outside the domain model.", + retry: "Re-delivery is not generally idempotent: internal command ids include a random UUID suffix.", + sourceId: "runtime-ingestion-buffer-dispatch", + }, + { + label: "Result committed", + boundary: "The internal command re-enters the same engine and commits the provider result as domain events.", + durable: "The projected result and its receipt now survive restart.", + volatile: "Any new downstream reactor work again crosses the same commit-before-publish seam.", + external: "The durable model has caught up with the observed harness result.", + retry: "The internal command receipt protects only that generated command id; it does not repair an earlier missed hot event.", + sourceId: "engine-receipt-publication-boundary", + }, +]; + +const resolved = phases.map(({ sourceId, ...phase }) => { + const source = getSourceReference(sourceId); + return { + ...phase, + source: { + label: sourceReferenceLabel(source), + href: sourceReferenceHref(source), + }, + }; +}); +const payload = JSON.stringify(resolved).replaceAll("<", "\\u003c"); +const first = resolved[0]; +--- + +
+
+ Crash-timing lab +

Move the crash across the delivery seam

+

Each position means “the process disappears immediately after this boundary.”

+
+ +
+
+ + + +
+ +

+ Use the arrow keys to move the simulated crash through the ordered phases. +

+ +
+
    + {resolved.map((phase, index) => ( +
  1. + +
  2. + ))} +
+
+ +

+ Position 1 of {resolved.length}: {first.label} +

+
+
+ Crash after +

{first.label}

+
+

{first.boundary}

+
+
Durable
{first.durable}
+
Volatile
{first.volatile}
+
External
{first.external}
+
Retry
{first.retry}
+
+ {first.source.label} +
+
+ + +
+ All crash positions +
    + {resolved.map((phase) => ( +
  1. + {phase.label} +

    {phase.boundary}

    +
    +
    Durable
    {phase.durable}
    +
    Volatile
    {phase.volatile}
    +
    External
    {phase.external}
    +
    Retry
    {phase.retry}
    +
    + {phase.source.label} +
  2. + ))} +
+
+ +
+ + + + diff --git a/src/components/DesktopProcessLab.astro b/src/components/DesktopProcessLab.astro new file mode 100644 index 0000000..3c7a51d --- /dev/null +++ b/src/components/DesktopProcessLab.astro @@ -0,0 +1,104 @@ +--- +interface Props { id?: string; } +const { id = "desktop-process" } = Astro.props; +const labId = `desktop-process-${id}`; +const modes = { + local: { label: "Host-local primary", process: "Electron main → primary local server child on macOS, Linux, or Windows → renderer window", transport: "fd3 bootstrap; fd4 host telemetry; fd5 diagnostics-demand control; HTTP / WebSocket", authority: "Electron main selects the child configuration and owns native APIs; renderer receives only curated IPC.", boot: "Main resolves the primary configuration, starts the host-local child, and probes its HTTP endpoint.", ready: "The ready callback gives the primary URL to the window service; the renderer is then served from the desktop target.", shutdown: "The pool stops the primary with SIGTERM and grace; an unexpected exit may instead enter the instance restart loop." }, + wsl: { label: "Windows + WSL", process: "Electron main → either a WSL-only primary, or a Windows primary plus optional WSL secondary → renderer connections", transport: "A Windows host-local primary uses fd3/fd4/fd5. WSL receives bootstrap on stdin because wsl.exe drops forwarded extra descriptors.", authority: "The pool owns these local child instances. WSL is a distinct Linux environment, not a replacement for the SSH gateway.", boot: "WSL-only resolves the primary as WSL. Dual mode starts Windows primary first, then forks reconciliation for a distro-specific secondary on a distinct port.", ready: "A WSL-only primary opens the window after its probe. In dual mode, Windows primary opens it while the WSL secondary reaches readiness independently.", shutdown: "Unregistering a WSL secondary closes its child scope; application finalization stops every registered instance concurrently." }, + ssh: { label: "SSH gateway", process: "Electron main → SSH environment manager → remote t3 process / tunnel → renderer connection", transport: "Curated renderer IPC asks main to discover, ensure, bootstrap, or disconnect an SSH environment; the remote endpoint is reached through the SSH path.", authority: "SSH is a remote environment gateway owned by the desktop SSH service. It is not an entry in the local backend-process pool.", boot: "The renderer requests a target; main delegates to the SSH environment manager, which can launch or connect to the remote environment.", ready: "A remote descriptor, bearer bootstrap, and WebSocket token establish a normal environment connection; primary-child readiness is unrelated.", shutdown: "Disconnecting the SSH environment tears down the gateway path. It is distinct from stopping local pool children during app shutdown." }, +} as const; +type ModeKey = keyof typeof modes; +const stages = ["boot", "ready", "shutdown"] as const; +type StageKey = typeof stages[number]; +const initialMode: ModeKey = "local"; +const initialStage: StageKey = "boot"; +--- + +
+
Interactive process lab · Chapter 32

Choose a delivery path, then advance its lifecycle

The same renderer can observe different transports; native and process authority stays in Electron main.

+
+
Delivery path
{Object.entries(modes).map(([key, mode]) => )}
+
+
+

{modes[initialMode].label} · Boot

+
    {stages.map((stage, index) =>
  1. {index + 1}{stage === "boot" ? "Boot" : stage === "ready" ? "Readiness" : "Shutdown"}
  2. )}
+

Boot

{modes[initialMode].label}

{modes[initialMode][initialStage]}

Process
{modes[initialMode].process}
Transport
{modes[initialMode].transport}
Authority
{modes[initialMode].authority}
+
Static process map{Object.values(modes).map((mode) => )}
PathProcess / transportBoundary
{mode.label}{mode.process}
{mode.transport}
{mode.authority}
+ +
+ + + + diff --git a/src/components/EvidenceClaim.astro b/src/components/EvidenceClaim.astro new file mode 100644 index 0000000..fc54ea0 --- /dev/null +++ b/src/components/EvidenceClaim.astro @@ -0,0 +1,26 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { + kind: "verified" | "documented" | "inference" | "future"; + title?: string; + refs: string[]; +} +const { kind, title, refs } = Astro.props; +if (refs.length === 0) throw new Error("EvidenceClaim requires at least one source reference."); +const labels = { + verified: "Verified behavior", + documented: "Documented intent", + inference: "Inference", + future: "Future / proposed", +}; +const sources = refs.map(getSourceReference); +--- + + diff --git a/src/components/Figure.astro b/src/components/Figure.astro new file mode 100644 index 0000000..1caa68a --- /dev/null +++ b/src/components/Figure.astro @@ -0,0 +1,25 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { + number: string; + title: string; + hint?: string; + caption: string; + textEquivalent: string; + sources: string[]; +} +const { number, title, hint, caption, textEquivalent, sources } = Astro.props; +if (sources.length === 0) throw new Error(`Figure ${number} requires at least one source reference.`); +const sourceRefs = sources.map(getSourceReference); +--- + +
+
Figure {number} · {title}{hint && {hint}}
+
+
Text equivalent

{textEquivalent}

+
Figure {number}. {caption}
+
+ {sourceRefs.map((source) => {sourceReferenceLabel(source)})} +
+
diff --git a/src/components/FlowLab.astro b/src/components/FlowLab.astro new file mode 100644 index 0000000..74ec7be --- /dev/null +++ b/src/components/FlowLab.astro @@ -0,0 +1,256 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface FlowStep { + label: string; + title: string; + detail: string; + actor?: string; + sourceIds: string[]; + tone?: "client" | "transport" | "durable" | "runtime" | "side-effect" | "failure" | "neutral"; +} +interface Props { + id: string; + title: string; + prompt: string; + steps: FlowStep[]; +} +const { id, title, prompt, steps } = Astro.props; +if (steps.length < 2) throw new Error(`FlowLab '${title}' requires at least two steps.`); +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) throw new Error(`FlowLab '${title}' requires a stable kebab-case id.`); +const labId = `flow-${id}`; +const toneLabels = { + client: "Client state", + transport: "Transport boundary", + durable: "Durable state", + runtime: "Runtime work", + "side-effect": "External side effect", + failure: "Failure state", + neutral: "Flow state", +} as const; +const resolved = steps.map(({ sourceIds, ...step }) => ({ + ...step, + toneLabel: toneLabels[step.tone ?? "neutral"], + sources: sourceIds.map((id) => { + const source = getSourceReference(id); + return { label: sourceReferenceLabel(source), href: sourceReferenceHref(source) }; + }), +})); +const payload = JSON.stringify(resolved).replaceAll("<", "\\u003c"); +--- + +
+
+ Interactive flow +

{title}

+

{prompt}

+
+
+ + + + 1 / {steps.length} +
+
+
+ + +
    + {resolved.map((step, index) => ( +
  1. + +
  2. + ))} +
+
+
+

Step 1 of {steps.length}: {resolved[0].label}

+
+
{resolved[0].actor ?? "Flow step"}{resolved[0].toneLabel}{resolved[0].label}
+

{resolved[0].title}

+

{resolved[0].detail}

+
+ {resolved[0].sources.map((source) => {source.label})} +
+
+ +
    + {resolved.map((step, index) => ( +
  1. + {index + 1}. {step.label} · {step.title} ({step.toneLabel}) +

    {step.detail}

    + {step.sources.map((source) => {source.label})} +
  2. + ))} +
+
+ + diff --git a/src/components/LayerMap.astro b/src/components/LayerMap.astro new file mode 100644 index 0000000..081b54e --- /dev/null +++ b/src/components/LayerMap.astro @@ -0,0 +1,20 @@ +--- +interface Node { label: string; slug?: string; } +interface Layer { label: string; nodes: Node[]; boundary?: boolean; tone?: "client" | "transport" | "durable" | "runtime" | "external"; } +interface Props { layers: Layer[]; } +const { layers } = Astro.props; +const base = import.meta.env.BASE_URL.endsWith("/") ? import.meta.env.BASE_URL : `${import.meta.env.BASE_URL}/`; +--- + +
+ {layers.map((layer) => ( +
+
{layer.label}
+
+ {layer.nodes.map((node) => node.slug + ? {node.label} + : {node.label})} +
+
+ ))} +
diff --git a/src/components/Mermaid.astro b/src/components/Mermaid.astro new file mode 100644 index 0000000..a206c51 --- /dev/null +++ b/src/components/Mermaid.astro @@ -0,0 +1,140 @@ +--- +interface Props { id: string; chart: string; label: string; } +const { id, chart, label } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error(`Mermaid '${label}' requires a stable kebab-case id.`); +} +const explorerId = `diagram-${id}`; +--- + +
+
+
+
+ {label} + + Diagram loading +
+
+ +
+

+ Zoom with the controls, +/, or Ctrl/ + trackpad scroll. Enable Pan to drag, use two-finger scrolling, or use the arrow keys. 0 fits the diagram; Esc leaves Pan or expanded view. +

+
+
+ + +
+
+ {label} + +
+
+
+
+
+ + diff --git a/src/components/MobileContinuityLab.astro b/src/components/MobileContinuityLab.astro new file mode 100644 index 0000000..5332bd4 --- /dev/null +++ b/src/components/MobileContinuityLab.astro @@ -0,0 +1,329 @@ +--- +interface Props { id: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("MobileContinuityLab requires a stable kebab-case id."); +} +const labId = `mobile-continuity-${id}`; +--- + +
+
+ Interactive continuity lab · Chapter 33 +

Protect intent before crossing a lifecycle boundary

+

Switch tracks and failure cases, then step through the exact guard that keeps an offline command or downloaded update from outrunning its durable state.

+
+ +
+
+ + +
+ +
+ + +
+ + + +
+
+ +
+
+

Outbox · offline creation

+

The local queue becomes visible before its file write settles

+

The immediate queued row is optimistic. Delivery cannot begin until the serialized mutation queue confirms that the atomic file write survived.

+
+ +
    + +
    +
    Guard in forceConfirm the exact queued object after its durable write
    +
    Authority after this stepmobile outbox file; server has received nothing
    +
    +
    + +

    Offline command outbox. Step 1 of 7.

    +
    + + +
    + Static mobile continuity ledger +
    + + + + + + + +
    BoundaryDurable prerequisiteSafety decisionRecovery
    Offline turn dispatchExact queued message confirmed after atomic-file writeWait for a connected environment; creations also wait for a live shellTransient/interrupted failures back off while the file remains
    Creation replayLive shell establishes whether the deterministic thread id already existsIf it exists, remove the queued creation without sending it againA failed cleanup can be retried without duplicating the thread
    Automatic OTA restartComposer drafts and outbox writes flushRestart only while truly backgrounded and no foreground handoff is activeFailed flush or unsafe handoff keeps the runtime alive and rearms the next background
    +
    +
    +
    + + + + diff --git a/src/components/OpenCodeRecoveryLab.astro b/src/components/OpenCodeRecoveryLab.astro new file mode 100644 index 0000000..9230521 --- /dev/null +++ b/src/components/OpenCodeRecoveryLab.astro @@ -0,0 +1,41 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("OpenCodeRecoveryLab requires a stable kebab-case id."); +} +const labId = `opencode-recovery-${id}`; + +const branches = [ + { label: "No valid cursor", result: "Create", detail: "An absent, malformed, or wrong-version cursor supplies no recognized native session id, so the adapter creates a new OpenCode session without a session.get probe.", durable: "The resulting id is returned as a current-version resume cursor for the outer provider-binding persistence path." }, + { label: "Confirmed missing", result: "Create", detail: "session.get reports a structured 404 / NotFoundError, so the stored native session is gone and a fresh session is permitted.", durable: "This is a native-context loss that is explicitly recognized, not a successful replay of old hot events." }, + { label: "Transient probe error", result: "Fail", detail: "Authentication, transport, server, or non-404 failures propagate instead of silently creating an empty conversation.", durable: "No new cursor is minted; the existing durable binding remains the recovery clue for a later retry." }, + { label: "Same directory", result: "Adopt", detail: "The existing session is reused after lexical/real-path comparison and its permission rules are reasserted for the current runtime mode.", durable: "The existing session id remains the cursor; upstream history remains provider-owned." }, + { label: "Different directory", result: "Fork", detail: "The adapter asks OpenCode to fork the adopted session into the requested cwd, preserving upstream conversation history, then updates permissions.", durable: "The new fork id replaces the returned resume cursor; T3 is not copying native history into its own event log." }, +]; +const payload = JSON.stringify(branches).replaceAll("<", "\\u003c"); +--- + +
    +
    Interactive recovery decision

    What does an OpenCode resume cursor actually do?

    Choose an observed condition; the outcome distinguishes provider-native recovery from durable product binding.

    +
    +
    +

    Selected {branches[0].label}: {branches[0].result}

    +
    {branches[0].result}

    {branches[0].label}

    Adapter decision
    {branches[0].detail}
    Durability boundary
    {branches[0].durable}
    +
    +
    All resume outcomes
      {branches.map((branch) =>
    1. {branch.label} → {branch.result}

      {branch.detail}

      {branch.durable}

    2. )}
    + +
    + + diff --git a/src/components/PermissionFlowLab.astro b/src/components/PermissionFlowLab.astro new file mode 100644 index 0000000..82a0500 --- /dev/null +++ b/src/components/PermissionFlowLab.astro @@ -0,0 +1,90 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) throw new Error("PermissionFlowLab requires a stable kebab-case id."); + +const modes = ["approval-required", "auto-accept-edits", "auto", "full-access"] as const; +const providers = { + codex: { label: "Codex", modes: { "approval-required": "untrusted · read-only · user reviewer", "auto-accept-edits": "on-request · workspace-write · user reviewer", auto: "on-request · workspace-write · auto_review", "full-access": "never · danger-full-access · user reviewer" }, approval: "native approval request → decision", input: "native tool request → answer map" }, + claude: { label: "Claude", modes: { "approval-required": "no explicit base-map entry", "auto-accept-edits": "acceptEdits", auto: "auto", "full-access": "bypassPermissions + allowDangerouslySkipPermissions; AskUserQuestion still routes to structured input" }, approval: "canUseTool callback → decision", input: "AskUserQuestion → answer map" }, + cursor: { label: "Cursor (ACP)", modes: { "approval-required": "prefer native approval-mode alias; permission callbacks still wait", "auto-accept-edits": "prefer implement-mode alias; permission callbacks still wait", auto: "prefer implement-mode alias; permission callbacks still wait", "full-access": "prefer implement-mode alias; auto-select offered allow option or wait" }, approval: "session/request_permission → selected/cancelled", input: "Cursor question extension → answer map" }, + grok: { label: "Grok (ACP)", modes: { "approval-required": "no session-mode mapping; raised callbacks wait", "auto-accept-edits": "no session-mode mapping; raised callbacks wait", auto: "no session-mode mapping; raised callbacks wait", "full-access": "auto-select offered allow-always/allow-once; otherwise wait" }, approval: "session/request_permission → selected/cancelled", input: "Grok question extension → answer map" }, + opencode: { label: "OpenCode", modes: { "approval-required": "broad operations ask; question is allowed", "auto-accept-edits": "broad operations ask; question is allowed", auto: "broad operations ask; question is allowed", "full-access": "allow all permission rules" }, approval: "permission.asked → permission.reply", input: "question.asked → question.reply" }, +} as const; +const initial = providers.codex; +const labId = `permission-flow-${id}`; +const payload = JSON.stringify({ providers, modes }).replaceAll("<", "\\u003c"); +--- + +
    +
    Interactive request router

    Trace a mode and a request without flattening provider behavior

    Choose a provider, stored T3 mode, and request shape. The panel distinguishes durable response intent from a live native reply.

    +
    + +
    Stored T3 mode
    {modes.map((mode, index) => )}
    +
    Request shape
    +
    +

    Codex, approval-required, approval.

    +
    +
    {initial.label}approval-required
    +

    Native starting behavior: {initial.modes["approval-required"]}

    +
      +
    1. 1Provider emits{initial.approval}
    2. +
    3. 2Runtime ingestioncanonical request activity; pauses the active assistant segment
    4. +
    5. 3Client commandthread.approval.respond records response intent
    6. +
    7. 4Reactor and serviceresolve the bound session and call the adapter
    8. +
    9. 5Provider replynative resolution later returns as activity
    10. +
    + +
    +
    Static provider × mode matrix
    {modes.map((mode) => )}{Object.values(providers).map((provider) => {modes.map((mode) => )})}
    Provider{mode}
    {provider.label}{provider.modes[mode]}
    + + +
    + + + + diff --git a/src/components/ProjectDiscoveryLab.astro b/src/components/ProjectDiscoveryLab.astro new file mode 100644 index 0000000..55b3d37 --- /dev/null +++ b/src/components/ProjectDiscoveryLab.astro @@ -0,0 +1,66 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ProjectDiscoveryLab requires a stable kebab-case id."); +} +const labId = `project-discovery-${id}`; +const cases = [ + { label: "Existing directory, valid t3.json", root: "Normalize the supplied path and verify it is a directory.", project: "A project.create command can claim this normalized root if no active project already uses it.", config: "Decode t3.json at that root; its defaultThreadEnvMode can participate only after a project-level override is absent.", identity: "If Git has a fetch remote, resolve a canonical repository identity for projection and cross-environment grouping." }, + { label: "Missing directory, creation not requested", root: "Normalization reports that the workspace root does not exist.", project: "No project is created because the command cannot pass root validation.", config: "There is no root at which to load t3.json.", identity: "No repository identity is derived." }, + { label: "Missing directory, creation requested", root: "The root service creates the directory recursively, verifies it, then returns the normalized path.", project: "The create command still must satisfy the one-active-project-per-normalized-root invariant.", config: "A missing t3.json is an ordinary absence, not an error.", identity: "A newly created empty directory has no Git-remote identity until it becomes a qualifying repository." }, + { label: "Existing regular file", root: "Normalization rejects it: a workspace root must be a directory.", project: "No project projection changes.", config: "t3.json is never consulted as project configuration for this invalid root.", identity: "No identity is derived." }, + { label: "Directory with invalid t3.json", root: "The workspace root itself remains valid.", project: "The durable project record can still exist at the root.", config: "The best-effort loader logs the read/decode problem and presents no usable file configuration, so defaults fall through.", identity: "Repository identity is independent of t3.json validity." }, +]; +const payload = JSON.stringify(cases).replaceAll("<", "\\u003c"); +--- + +
    +
    Filesystem decision explainer

    What becomes a T3 project?

    Choose one observed filesystem state. The four answers keep root validation, durable projection, checked-in configuration, and Git identity separate.

    +
    + + +
    +

    Selected: {cases[0].label}

    +
    +
    1. Root
    {cases[0].root}
    +
    2. Project
    {cases[0].project}
    +
    3. t3.json
    {cases[0].config}
    +
    4. Identity
    {cases[0].identity}
    +
    +
    All filesystem outcomes
      {cases.map((item) =>
    1. {item.label}

      Root: {item.root}

      Project: {item.project}

      t3.json: {item.config}

      Identity: {item.identity}

    2. )}
    + + +
    + + + + diff --git a/src/components/ProjectionCursorLab.astro b/src/components/ProjectionCursorLab.astro new file mode 100644 index 0000000..9e9403d --- /dev/null +++ b/src/components/ProjectionCursorLab.astro @@ -0,0 +1,223 @@ +--- +const lanes = [ + { id: "projects", label: "Projects", table: "projection_projects", role: "project fields", required: true }, + { id: "messages", label: "Messages", table: "projection_thread_messages", role: "message bodies", required: true }, + { id: "plans", label: "Plans", table: "projection_thread_proposed_plans", role: "proposed plans", required: true }, + { id: "activities", label: "Activities", table: "projection_thread_activities", role: "activity log", required: true }, + { id: "sessions", label: "Sessions", table: "projection_thread_sessions", role: "runtime session", required: true }, + { id: "turns", label: "Turns", table: "projection_turns", role: "turns + checkpoint metadata", required: false }, + { id: "checkpoints", label: "Checkpoints", table: "no table", role: "registered no-op", required: true }, + { id: "approvals", label: "Approvals", table: "projection_pending_approvals", role: "approval state", required: false }, + { id: "threads", label: "Threads", table: "projection_threads", role: "shell summary (last)", required: true }, +] as const; + +const events = [ + "project.created", + "thread.created", + "thread.message-sent", +] as const; +--- + +
    +
    + Interactive fold lab +

    One event stream, nine projector cursors

    +

    + Step through three durable events. Every registered projector is considered in + order, including no-ops; the safe snapshot watermark is the slowest required + cursor, not the event-store head. +

    +
    + +
    + + + + +
    + +

    + No sample event has been folded. All projector cursors are at 0. +

    + +
    +
    Event-store head0
    +
    Safe snapshot sequence0
    +
    Current eventnone
    +
    + +
    + Normal command control flow + outer SQL begins → append → projector SQL + cursor → optional filesystem cleanup → accepted receipt → outer commit + Cleanup runs before commit but is not enlisted in SQL rollback. +
    + +
    +
      + {lanes.map((lane, index) => ( +
    1. + +
      + {lane.label} + + {lane.table} · {lane.role} · + {lane.required ? " snapshot-required" : " auxiliary cursor"} + +
      + 0 +
    2. + ))} +
    +
    + +
    + Start with the cursor, not a promise of eventual consistency. +

    On a normal command, all nine folds run sequentially before the command transaction commits.

    +
    + + + +
    +

    Static reference: the normal third event leaves every required cursor at 3, so the safe snapshot sequence is 3.

    +

    1,001-event bootstrap case: the default total read limit stops every lane at 1,000 while the event-store head is 1,001.

    + + + + {lanes.map((lane, index) => )} + +
    OrderProjectorRead sideWatermark roleAt sequence 3
    {index + 1}{lane.label}{lane.table}{lane.required ? "required" : "auxiliary"}3
    +
    + + +
    + + + + diff --git a/src/components/ProviderRoutingLab.astro b/src/components/ProviderRoutingLab.astro new file mode 100644 index 0000000..02c4a88 --- /dev/null +++ b/src/components/ProviderRoutingLab.astro @@ -0,0 +1,216 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ProviderRoutingLab requires a stable kebab-case id."); +} + +const stages = [ + { label: "Settings", short: "settings", question: "What was authored?" }, + { label: "Hydration", short: "merge", question: "Does explicit or legacy config win?" }, + { label: "Construction", short: "scope", question: "Can the driver decode and create it?" }, + { label: "Discovery", short: "view", question: "Is it live or only a shadow snapshot?" }, + { label: "Binding", short: "route", question: "Which exact instance does the thread name?" }, + { label: "Operation", short: "recover", question: "Can the current adapter adopt or resume?" }, +] as const; + +const scenarios = { + legacy: { + label: "Legacy Codex default", + authored: "providers.codex exists; providerInstances.codex is absent.", + hydration: "Synthesize the default instance id `codex` from the legacy typed blob.", + construction: "Registered Codex driver decodes config and creates one scoped live instance.", + discovery: "UI snapshot and routable adapter both use instanceId `codex`.", + binding: "Thread binding names `codex`; driver kind verifies `codex`.", + operation: "Exact adapter lookup succeeds; an active session routes immediately.", + outcome: "Routable default instance", + secret: "Only marked sensitive environment values are split/redacted.", + tone: "success", + sourceIds: ["provider-instance-hydration", "provider-driver-instance-spi", "provider-adapter-registry-live"], + }, + explicit: { + label: "Explicit work account", + authored: "providerInstances.codex_work uses driver `codex`; a legacy default may coexist.", + hydration: "Keep `codex_work` exactly as authored. It does not overwrite the default `codex` key.", + construction: "The same driver factory creates independent adapter, snapshot, and text-generation closures.", + discovery: "Both instances can expose different health, model, and auth observations.", + binding: "A work thread persists `providerInstanceId: codex_work`.", + operation: "Lookup cannot fall back to `codex`; it routes the work instance only.", + outcome: "Two same-driver instances stay isolated", + secret: "Sensitive per-instance environment can point each process at different homes or credentials.", + tone: "success", + sourceIds: ["provider-instance-identity-contract", "provider-instance-registry-tests", "provider-service-start-session"], + }, + override: { + label: "Explicit default overrides legacy", + authored: "Both providers.codex and providerInstances.codex are present.", + hydration: "The explicit `providerInstances.codex` envelope wins; no legacy copy is synthesized for that id.", + construction: "Decode the explicit opaque config and compute enabled state; nested false dominates.", + discovery: "Exactly one default-id snapshot is produced from the explicit entry.", + binding: "Existing default bindings still name `codex`, now resolving the replacement configuration.", + operation: "If the object changed, the old scope closes first; later work may need cursor recovery.", + outcome: "Explicit configuration wins, without live-session handoff", + secret: "A redacted sensitive patch preserves the prior secret rather than writing an empty value.", + tone: "warning", + sourceIds: ["provider-instance-hydration", "provider-instance-enabled-precedence", "provider-instance-registry-reconcile"], + }, + shadow: { + label: "Unknown fork driver", + authored: "providerInstances.research names valid slug `forkAgent`, absent from this build.", + hydration: "The open driver slug parses successfully and remains in the effective map.", + construction: "No registered driver exists, so construction yields an unavailable shadow.", + discovery: "The UI sees disabled/error/unavailable with its exact reason.", + binding: "A persisted binding can still name `research`, but no live adapter is listed.", + operation: "getByInstance fails; the service does not silently choose another account or driver.", + outcome: "Visible configuration, intentionally unroutable", + secret: "Unknown opaque config is preserved; the contracts layer does not attempt driver-specific decoding.", + tone: "failure", + sourceIds: ["provider-instance-identity-contract", "provider-instance-build-shadow", "provider-unavailable-shadow"], + }, + rebuilt: { + label: "Changed instance with cursor", + authored: "codex_work config changes while a thread binding and resume cursor remain persisted.", + hydration: "The same instance id now carries a different entry.", + construction: "Close the old child scope before creating the replacement instance and stream.", + discovery: "Registries re-pull the replacement object after the change tick.", + binding: "SQLite still maps the thread to codex_work and retains opaque resume data.", + operation: "No active replacement session: an eligible operation calls startSession with saved cursor/mode/cwd/model.", + outcome: "Lazy resume attempt; not zero-downtime migration", + secret: "Changed sensitive values are materialized before the new driver scope is created.", + tone: "warning", + sourceIds: ["provider-instance-registry-reconcile", "provider-registry-live-sync", "provider-service-session-recovery"], + }, + stranded: { + label: "Removed instance binding", + authored: "The thread still names codex_work, but settings removed that instance.", + hydration: "codex_work disappears from the effective map.", + construction: "The old child scope closes and no replacement is created.", + discovery: "The snapshot is pruned and live adapter lookup excludes the id.", + binding: "The durable thread binding is not automatically reassigned or deleted.", + operation: "Exact route lookup fails; another Codex instance cannot claim the thread implicitly.", + outcome: "Durable binding stranded until explicit repair/configuration", + secret: "Removing a sensitive environment entry also removes its named secret through settings logic.", + tone: "failure", + sourceIds: ["provider-instance-registry-reconcile", "provider-adapter-registry-live", "provider-service-session-recovery"], + }, + nocursor: { + label: "Live instance, no resume state", + authored: "The configured instance is healthy; the thread binding exists after its live session was lost.", + hydration: "No settings change is required.", + construction: "The current instance and adapter are live.", + discovery: "Health does not imply ownership of this thread's native session.", + binding: "The route is exact but its resume cursor is null/absent.", + operation: "Recovery-capable operations return validation failure instead of starting an unrelated fresh conversation.", + outcome: "Routable instance, unrecoverable conversation", + secret: "Credentials may be healthy and still cannot reconstruct missing provider continuation state.", + tone: "failure", + sourceIds: ["provider-service-session-recovery", "provider-session-directory"], + }, + opencode: { + label: "External OpenCode password", + authored: "An external serverUrl and serverPassword live in the OpenCode config blob.", + hydration: "The explicit config is decoded by the OpenCode driver.", + construction: "No local server scope is owned for an external URL; the client uses supplied Basic auth.", + discovery: "Connection/auth health belongs to this instance snapshot.", + binding: "Threads still route by instance id, never by server URL or password.", + operation: "The adapter calls the external server for that configured instance.", + outcome: "Routable external instance with a plaintext-settings exception", + secret: "serverPassword is documented and tested as plaintext in settings; password UI styling is not encryption.", + tone: "warning", + sourceIds: ["opencode-password-settings", "opencode-password-persistence-test", "opencode-external-basic-auth"], + }, +} as const; + +const resolved = Object.fromEntries(Object.entries(scenarios).map(([key, scenario]) => [key, { + ...scenario, + sources: scenario.sourceIds.map((sourceId) => { const source = getSourceReference(sourceId); return { href: sourceReferenceHref(source), label: sourceReferenceLabel(source) }; }), +}])); +const initial = resolved.legacy; +const labId = `provider-routing-${id}`; +const payload = JSON.stringify({ stages, scenarios: resolved }).replaceAll("<", "\\u003c"); +--- + +
    +
    Interactive fleet router

    Which configured runtime receives the thread?

    Walk from authored settings to one exact route. Discovery visibility, live behavior, and resume eligibility are different checks.

    + +
    +
    + + +
    +
    + + +

    {initial.label}; stage 1 of {stages.length}: {stages[0].label}. {initial.outcome}.

    + +
    +
    {stages[0].question}

    {stages[0].label}

    {initial.outcome}
    +

    {initial.authored}

    +
    +
    Authored

    {initial.authored}

    Effective map

    {initial.hydration}

    +
    Live construction

    {initial.construction}

    Discovery

    {initial.discovery}

    +
    Durable binding

    {initial.binding}

    Operation result

    {initial.operation}

    +
    + +
    {initial.sources.map((source) => {source.label})}
    +
    +
    + +
    Static fleet-routing matrix
    {Object.values(resolved).map((scenario) => )}
    ScenarioHydration / constructionBinding / operationOutcome and secret boundary
    {scenario.label}{scenario.hydration} {scenario.construction}{scenario.binding} {scenario.operation}{scenario.outcome} {scenario.secret}
    + + +
    + + + + diff --git a/src/components/ReachabilityRecoveryLab.astro b/src/components/ReachabilityRecoveryLab.astro new file mode 100644 index 0000000..6252ce9 --- /dev/null +++ b/src/components/ReachabilityRecoveryLab.astro @@ -0,0 +1,176 @@ +--- +interface Props { id: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ReachabilityRecoveryLab requires a stable kebab-case id."); +} +const labId = `reachability-recovery-${id}`; +--- + +
    +
    + Interactive boundary lab · Chapter 36 +

    A signal can wake recovery; it cannot replace synchronization

    +

    Choose a track and a deliberate event. The ledger shows which owner acts, what may be inferred, and the next authoritative read.

    +
    + +
    +
    + + +
    + +
    + +
    +

    Connection supervision

    +

    One environment lease has closed

    +

    The environment-scoped supervisor clears its old session, records a new generation only after establishment, and owns any retry.

    + +
    +
    Owner
    Environment supervisor for this environment
    +
    Signal means
    The active RPC lease is no longer usable.
    +
    Do not infer
    That shell or thread projections are current.
    +
    Authoritative next step
    Obtain a replacement session, then refresh/subscribe the scoped projections.
    +
    +
    +

    Connection supervision: session closes.

    +
    + + +
    + Static recovery ledger +
    + + + + + + + + + + +
    TrackEventOwnerSafe conclusionRequired follow-up
    ConnectionSocket closesOne environment supervisorThe old lease is unusable; retry policy belongs to the supervisor.A replacement session changes generation; shell and thread synchronize independently.
    ConnectionDevice goes offlineOne environment supervisorRelease the active lease and wait for an external signal; do not spend retry attempts.Reconnect only after online/wakeup input permits it.
    ConnectionForeground wakeupOne environment supervisorA healthy lease can be probed instead of discarded.A failed probe leads into the same owned recovery path.
    NotificationApproval push arrivesMobile navigation and the selected environment stateThe notification names a route-worthy event, not a thread snapshot.Navigate, connect if needed, then reconcile shell/thread state from the environment.
    NotificationRelay registration is acceptedRelay/device-registration boundaryThe relay can replay its aggregate; a local permission alone was never delivery proof.Use normal synchronization to repair state and remove stale UI assumptions.
    NotificationAPNs delivery is delayed or absentNormal connection and synchronization pathThere is no promised notification receipt or durable state transfer.The app later converges through its environment supervisor and projections.
    +
    +
    +
    + + + + diff --git a/src/components/ReceiptWindowLab.astro b/src/components/ReceiptWindowLab.astro new file mode 100644 index 0000000..016c80a --- /dev/null +++ b/src/components/ReceiptWindowLab.astro @@ -0,0 +1,595 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { + id: string; +} + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ReceiptWindowLab requires a stable kebab-case id."); +} + +const sourceIds = [ + "command-receipt-schema", + "command-receipt-handling", + "engine-rejected-receipt", + "engine-commit-publication", + "turn-atomic-batch", + "hot-reactor-no-replay", + "command-commit-acknowledgement", + "provider-turn-reactor", +]; +const sources = Object.fromEntries(sourceIds.map((sourceId) => { + const source = getSourceReference(sourceId); + return [sourceId, { label: sourceReferenceLabel(source), href: sourceReferenceHref(source) }]; +})); +const payload = JSON.stringify({ sources }).replaceAll("<", "\\u003c"); +const labId = `receipt-window-${id}`; +--- + +
    +
    + Interactive retry laboratory +

    What does this command id remember?

    +

    Configure the durable receipt and the original delivery window, then replay the id. The result separates SQL deduplication from hot delivery and provider execution.

    +
    + +
    + + + + +
    + +

    The delivery window describes the accepted attempt whose receipt is being replayed.

    + + +
      +
    1. 1Accepted SQLcomplete
    2. +
    3. 2Hot publishcomplete
    4. +
    5. 3RPC responsereceived
    6. +
    7. 4Providernot proven
    8. +
    + +

    + Accepted receipt, same aggregate, same intent: return the stored sequence without new events. Provider execution is not proven. +

    + +
    +
    +
    Engine decision

    Replay the accepted sequence

    + deduplicated +
    +

    The engine finds the accepted row before the decider and returns its stored resultSequence.

    +
    +
    Durable record
    The original event batch, projections, and accepted receipt remain committed.
    +
    Events and delivery
    The retry appends zero events and republishes zero events.
    +
    Client result
    The retry receives the stored last sequence.
    +
    Payload binding
    The receipt checks aggregate kind and id, not command type or a payload fingerprint.
    +
    Provider meaning
    The sequence acknowledges durable intent only; provider acceptance or completion is outside the receipt.
    +
    +
    + {sourceIds.slice(0, 2).map((sourceId) => {sources[sourceId].label})} +
    +
    + +
    + Static receipt and crash-window matrices +
    +

    Receipt decision matrix

    +
    + + + + + + + + + +
    Stored rowRetry targetDecisionDoes body matter?
    acceptedsame aggregatereturn stored sequence; no decide, append, or republishno type or payload comparison
    accepteddifferent aggregatecommand-id conflictconflict occurs before status replay
    rejectedsame aggregatereturn previously-rejected error; no re-evaluationno type or payload comparison
    rejecteddifferent aggregatecommand-id conflictconflict occurs first
    noneany aggregatedecide the normalized command nowthe supplied body is the new candidate
    +
    +
    +
    +

    Accepted-attempt delivery windows

    +
    + + + + + + + + + +
    WindowDurable SQLHot deliverySame-id retry
    ordinary response receivedcomplete batch + receiptall events offeredstored sequence
    hard crash after commitcomplete batch + receiptnone in failed processstored sequence; no republish
    hard crash during publicationcomplete batch + receiptsome prefix; exact prefix depends on the crash pointstored sequence; no missing-suffix replay
    response lostcomplete batch + receiptall events offeredstored sequence
    provider later failscomplete batch + receiptall events offeredstored sequence; no new provider request
    +
    +
    +
    + + +
    + + + + diff --git a/src/components/RecoveryMatrixLab.astro b/src/components/RecoveryMatrixLab.astro new file mode 100644 index 0000000..593ef80 --- /dev/null +++ b/src/components/RecoveryMatrixLab.astro @@ -0,0 +1,240 @@ +--- +import { + getSourceReference, + sourceReferenceHref, + sourceReferenceLabel, +} from "../lib/sources"; + +interface Props { + id?: string; +} + +const { id = "cross-store-recovery" } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("RecoveryMatrixLab requires a stable kebab-case id."); +} + +const rows = [ + { + label: "Service update", + pair: "SQLite + WAL + SHM", + order: "Persist pending update → stop old child → stage and sync triplet backup → run trial; marker is written only before rollback restore", + residue: "Pending service state identifies the unfinished trial. A restore marker inside the backup identifies an interrupted rollback restore.", + startup: "Conditional. Pending state resumes the trial when no restore marker exists; a restore marker makes startup retry the rollback restoration first.", + boundary: "Strongest recovery path, but it covers the SQLite triplet only—not attachments, settings, logs, or Git refs.", + verdict: "Journaled", + tone: "safe", + sourceIds: ["service-update-recovery"], + }, + { + label: "Settings update", + pair: "settings.json + secret files", + order: "Write/remove secrets → normalize redacted settings → rename settings JSON → update cache", + residue: "A failed JSON write can leave a new orphan secret or a redacted pointer whose old secret was removed.", + startup: "No pair reconciler. Missing or malformed settings fall back to defaults; missing secret materializes as empty.", + boundary: "Each file operation has local safeguards, but the group is not one transaction.", + verdict: "Saga gap", + tone: "warning", + sourceIds: ["settings-load-fallbacks", "settings-secret-order", "settings-atomic-write", "secret-store-atomic-boundary"], + }, + { + label: "Attachments", + pair: "image files + SQL references", + order: "Normalize and write file before dispatch; projector commits cursor before post-transaction cleanup", + residue: "Rejected/retried commands can orphan files; failed cleanup after cursor advance is not retried from that event; a delete can precede a later outer rollback.", + startup: "The pinned production-code audit found no repository-wide orphan collector. Cursor advancement can prevent the same cleanup from replaying.", + boundary: "Path validation is strong; lifecycle atomicity across filesystem and SQLite is not.", + verdict: "Unreconciled", + tone: "failure", + sourceIds: ["attachment-path-safety", "normalizer-staging-boundary", "attachment-projection-cleanup", "engine-commit-publication"], + }, + { + label: "Terminal history", + pair: "memory/PTY + history file", + order: "Update memory → coalesce for 40 ms → overwrite history; explicit close persists and drains", + residue: "A hard crash can lose the coalescing window. Direct overwrite creates partial-write risk; saved text cannot reconstruct PTY process state.", + startup: "The saved text is loaded on first open, then a new PTY starts. General scope cleanup does not prove a history drain.", + boundary: "Useful continuity of text, not a transactional terminal replay.", + verdict: "Best effort", + tone: "warning", + sourceIds: ["terminal-history-defaults", "terminal-history-persistence", "terminal-output-persistence-order", "terminal-explicit-close", "terminal-scope-finalizer", "terminal-lazy-history-open"], + }, + { + label: "Checkpoint", + pair: "hidden Git ref + SQL checkpoint metadata", + order: "Build isolated-index tree → update hidden ref → dispatch checkpoint metadata", + residue: "A crash can orphan the ref. Revert mutates workspace, provider state, and newer refs before recording completion.", + startup: "The pinned production-code audit found no ref/SQL reconciler. Capture also collapses staged and unstaged content; restore resets the index toward HEAD.", + boundary: "File content is recoverable on a successful restore, but staging boundaries and cross-store saga progress are not.", + verdict: "Unjournaled", + tone: "failure", + sourceIds: ["checkpoint-git-capture-restore", "checkpoint-capture-dispatch-order", "checkpoint-revert-saga"], + }, +]; + +const resolved = rows.map(({ sourceIds, ...row }) => ({ + ...row, + sources: sourceIds.map((sourceId) => { + const source = getSourceReference(sourceId); + return { label: sourceReferenceLabel(source), href: sourceReferenceHref(source) }; + }), +})); +const payload = JSON.stringify(resolved).replaceAll("<", "\\u003c"); +const first = resolved[0]; +--- + +
    +
    + Recovery matrix +

    Select a persistence boundary

    +

    The table stays complete; selection expands one crash story without hiding the comparison.

    +
    + +
    + + + + + + {resolved.map((row, index) => ( + + + + + + + ))} + +
    BoundaryWrite orderCrash residueStartup repair
    + + {row.order}{row.residue}{row.startup}
    +
    + +

    + Selected {first.label}: {first.verdict} +

    +
    +
    {first.verdict}

    {first.label} · {first.pair}

    +

    {first.boundary}

    + +
    + + +
    + + + + diff --git a/src/components/ReleaseOperationsLab.astro b/src/components/ReleaseOperationsLab.astro new file mode 100644 index 0000000..af3e1e3 --- /dev/null +++ b/src/components/ReleaseOperationsLab.astro @@ -0,0 +1,286 @@ +--- +interface Props { id: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("ReleaseOperationsLab requires a stable kebab-case id."); +} +const labId = `release-operations-${id}`; +--- + +
    +
    + Interactive operations lab · Chapter 38 +

    One release, three replacement boundaries, four signal lanes

    +

    Choose a lens, select a teaching case, and move the marker yourself. The model shows the point at which each owner may proceed—and the boundary that keeps it from doing so.

    +
    + +
    +
    + + + +
    + +
    + + +
    + + + +
    +
    + +
    +
    +

    Release graph · stable exact-version path

    +

    Publishing the CLI unblocks every client that can request a server update

    +

    The graph does not update a machine. It only makes a matching, exact runtime available before a client can advertise itself.

    +
    +
    +
    +
    Guard
    publish `t3@V` before a client at V is exposed
    +
    Owner now
    release workflow
    +
    Failure boundary
    a client cannot target a package that has not published
    +
    +
    + +

    Release graph. Step 1.

    +
    + + +
    + Static operations ledger +
    + + + + + + + + + +
    FlowProceed only afterOwnerIf it cannot proceed
    Exact server update`t3@<version>` publishes before client releaserelease workflow, then service launcherclient version cannot be offered before the matching runtime exists
    Desktop applicationuser chooses download and then install; pooled backends stopdesktop updaterstate records an error or remains downloaded for a later install
    Boot-service serverexact runtime preflight, SQLite snapshot, target reports preparedstable launcherrollback restores snapshot and selects the old runtime
    Mobile OTAfingerprint-compatible bundle, flushed intent, safe true backgroundmobile update coordinatordefer to a later lifecycle transition
    Diagnosticsdestination and authorization vary by laneanalytics/tracer/resource serviceslocal traces can remain local; resource history stays bounded in memory
    +
    +
    +
    + + + + diff --git a/src/components/ScenarioLab.astro b/src/components/ScenarioLab.astro new file mode 100644 index 0000000..11f0337 --- /dev/null +++ b/src/components/ScenarioLab.astro @@ -0,0 +1,124 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Scenario { + label: string; + title: string; + summary: string; + facts: string[]; + sourceIds: string[]; + tone?: "safe" | "warning" | "failure" | "neutral"; +} +interface Props { + id: string; + title: string; + prompt: string; + scenarios: Scenario[]; +} +const { id, title, prompt, scenarios } = Astro.props; +if (scenarios.length < 2) throw new Error(`ScenarioLab '${title}' requires at least two scenarios.`); +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) throw new Error(`ScenarioLab '${title}' requires a stable kebab-case id.`); +const labId = `scenario-${id}`; +const toneLabels = { safe: "Expected path", warning: "Caveat", failure: "Failure path", neutral: "Alternative" } as const; +const resolved = scenarios.map(({ sourceIds, ...scenario }) => ({ + ...scenario, + toneLabel: toneLabels[scenario.tone ?? "neutral"], + sources: sourceIds.map((id) => { + const source = getSourceReference(id); + return { label: sourceReferenceLabel(source), href: sourceReferenceHref(source) }; + }), +})); +const payload = JSON.stringify(resolved).replaceAll("<", "\\u003c"); +--- + +
    +
    Interactive lab

    {title}

    {prompt}

    +
    + {resolved.map((scenario, index) => ( + + ))} +
    +

    Scenario 1 of {scenarios.length}: {resolved[0].label}

    +
    +
    {resolved[0].label}{resolved[0].toneLabel}
    +

    {resolved[0].title}

    +

    {resolved[0].summary}

    +
      {resolved[0].facts.map((fact) =>
    • {fact}
    • )}
    +
    + {resolved[0].sources.map((source) => {source.label})} +
    +
    +
      + {resolved.map((scenario) => ( +
    1. {scenario.label} · {scenario.title} ({scenario.toneLabel})

      {scenario.summary}

        {scenario.facts.map((fact) =>
      • {fact}
      • )}
      {scenario.sources.map((source) => {source.label})}
    2. + ))} +
    + +
    + + diff --git a/src/components/SourceExcerpt.astro b/src/components/SourceExcerpt.astro new file mode 100644 index 0000000..de11f77 --- /dev/null +++ b/src/components/SourceExcerpt.astro @@ -0,0 +1,61 @@ +--- +import excerpts from "../generated/excerpts.json"; +import lock from "../../sources/t3code.lock.json"; + +interface SourceRecord { + id: string; + path: string; + start: number; + end: number; + language: string; + label?: string; + code: string; + checksum: string; +} + +interface Props { + id: string; + focus?: number[]; + note?: string; +} + +const { id, focus = [], note } = Astro.props; +const record = (excerpts as Record)[id]; +if (!record) throw new Error(`Unknown source excerpt '${id}'. Run npm run source:sync.`); +const lines = record.code.replace(/\n$/, "").split("\n"); +const sourceUrl = `${lock.repository}/blob/${lock.commit}/${record.path}#L${record.start}-L${record.end}`; +--- + +
    +
    + + + {record.path}:{record.start}–{record.end} ↗ + + verbatim · {record.language} · {record.checksum.slice(0, 8)} + +
    +
    +
    {lines.map((line, index) => {
    +      const lineNumber = record.start + index;
    +      return {line || "\u00a0"}{index < lines.length - 1 ? "\n" : ""};
    +    })}
    +
    + {note &&
    Read this as: {note}
    } +
    + + diff --git a/src/components/SourceList.astro b/src/components/SourceList.astro new file mode 100644 index 0000000..a9e7230 --- /dev/null +++ b/src/components/SourceList.astro @@ -0,0 +1,17 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Props { ids: string[]; title?: string; } +const { ids, title = "Source trail" } = Astro.props; +const refs = ids.map(getSourceReference); +--- + + diff --git a/src/components/SourceSnapshot.astro b/src/components/SourceSnapshot.astro new file mode 100644 index 0000000..506fdd2 --- /dev/null +++ b/src/components/SourceSnapshot.astro @@ -0,0 +1,10 @@ +--- +import lock from "../../sources/t3code.lock.json"; +import Stats from "./Stats.astro"; +--- + + diff --git a/src/components/Stats.astro b/src/components/Stats.astro new file mode 100644 index 0000000..93514cc --- /dev/null +++ b/src/components/Stats.astro @@ -0,0 +1,10 @@ +--- +interface Stat { value: string; label: string; } +interface Props { items: Stat[]; } +const { items } = Astro.props; +--- + +
    + {items.map((item) =>
    {item.value}{item.label}
    )} +
    + diff --git a/src/components/SynchronizedTraceLab.astro b/src/components/SynchronizedTraceLab.astro new file mode 100644 index 0000000..fe7f04b --- /dev/null +++ b/src/components/SynchronizedTraceLab.astro @@ -0,0 +1,266 @@ +--- +interface Props { id: string; } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("SynchronizedTraceLab requires a stable kebab-case id."); +} +const labId = `synchronized-trace-${id}`; +--- + +
    +
    + Interactive synthesis lab · Chapter 39 +

    Move one trace through the owner that acts next

    +

    Select a complete trace, then advance deliberately. The marker crosses the owner that acts next; its final boundary says what does—and does not—converge.

    +
    + +
    +
    + + + + + + +
    + +
    + +

    Step 1 of 6

    + + +
    + +
    +

    Trace 1 · Local first turn

    +

    Client sends one existing-thread command

    +

    The user action enters the environment through an authorized RPC method; no provider work has happened yet.

    + + + +
    +
    Owner now
    client and RPC entry policy
    +
    Handoff / evidence
    typed turn command reaches the selected environment
    +
    Durable fact now
    none yet
    +
    Boundary if it stops here
    an RPC failure is not a provider failure and does not create an accepted turn
    +
    +
    +

    Local first turn. Step 1 of 6.

    +
    + + +
    + Static six-trace ledger +
    + + + + + + + + + + +
    TraceOwner sequenceDurable evidenceConvergence or failure boundary
    Local first turnclient → RPC/engine → SQLite → provider reactor/adapter → engine → client stateaccepted event, projections, and receipt commit togetherhot reactor delivery is not replayed after a crash; later projections only show committed facts
    Relay-connected mobile turnphone → relay control plane → selected environment → relay bootstrap return → direct mobile session → environment statedevice-held DPoP-bound environment session material and environment projectionsrelay launch authorization is not thread synchronization; ordinary traffic bypasses the relay
    Approval round-tripprovider → runtime ingestion → pending projection → client → response intent → provider reactorpending request and response-requested event are separate durable factsnative provider reply is a later hot handoff where a stale or unknown request can fail; runtime-mode labels do not equal provider semantics
    Offline mobile drainmobile atom → atomic outbox file → live shell → environment receipt/result → phone cleanup → later projection reconciliationconfirmed phone file, then remote command receiptthere is no transaction shared by phone storage and server SQLite; cleanup follows the command result, while projections reconcile separately
    Checkpoint diff / revertcompletion → Git hidden ref/diff → checkpoint projection → durable revert request → ordered saga → engine completionhidden ref precedes checkpoint metadata; the request and later completion are separate orchestration factsrestore can happen before provider rollback; later failure can leave a real partial state
    Stable exact updaterelease automation → exact npm runtime → client exposure → connected-client request → server preflight → stable launcher trialexact package publication, then launcher pending/trial/commit statepublish does not replace a machine; launcher can roll back a failed trial before commit
    +
    +
    +
    + + + + diff --git a/src/components/ThreadProjectionLab.astro b/src/components/ThreadProjectionLab.astro new file mode 100644 index 0000000..7e99363 --- /dev/null +++ b/src/components/ThreadProjectionLab.astro @@ -0,0 +1,240 @@ +--- +interface Props { id?: string; } +const { id = "thread-projection" } = Astro.props; +const labId = `thread-projection-${id}`; +const scenarios = { + active: { + label: "Active turn", + fields: ["threadId", "messages", "session.status", "activities", "draft", "pinnedAt"], + note: "A running session and a local draft coexist; the draft is not a durable message yet.", + }, + review: { + label: "Review pending", + fields: ["threadId", "messages", "turn.diff", "checkpoint", "review.comments", "pinnedAt"], + note: "The review surface reads the turn diff and comments; chat keeps the conversational context.", + }, + quiet: { + label: "Quiet work log", + fields: ["threadId", "messages", "activities", "task.latest", "session.status", "orderedAt"], + note: "A quiet thread can still retain activity and ordering metadata without becoming a scheduler record.", + }, +} as const; + +const projections = { + chat: { + label: "Chat timeline", + consumes: ["messages", "session.status", "activities"], + suppresses: ["task.latest", "review.comments", "orderedAt"], + server: "Send message · interrupt turn", + local: "Scroll position · collapsed activity", + copy: "Conversation first: lifecycle details remain compact activity affordances.", + }, + composer: { + label: "Composer + optimistic state", + consumes: ["draft", "messages", "session.status"], + suppresses: ["turn.diff", "pinnedAt", "task.latest"], + server: "Submit message · cancel turn", + local: "Draft text · optimistic pending row", + copy: "The composer can feel immediate while the canonical message waits for the accepted receipt.", + }, + log: { + label: "Quiet work log", + consumes: ["activities", "task.latest", "session.status"], + suppresses: ["draft", "review.comments", "turn.diff"], + server: "Open thread · resume eligible work", + local: "Expanded rows · filter", + copy: "A compact activity projection preserves useful lifecycle signals without replaying every token.", + }, + agents: { + label: "Agents / subagents", + consumes: ["task.latest", "activities", "session.status"], + suppresses: ["draft", "pinnedAt", "review.comments"], + server: "Interrupt agent · open thread", + local: "Roster grouping · selected agent", + copy: "The roster is derived from task lifecycle evidence; it is not a second canonical transcript.", + }, + review: { + label: "Review / diff", + consumes: ["turn.diff", "checkpoint", "review.comments"], + suppresses: ["draft", "task.latest", "orderedAt"], + server: "Post review comment · restore checkpoint", + local: "Selected lines · diff mode", + copy: "Review narrows attention to changed files and anchored comments while retaining the thread identity.", + }, + sidebar: { + label: "Ordered / pinned sidebar", + consumes: ["threadId", "pinnedAt", "orderedAt", "messages"], + suppresses: ["draft", "turn.diff", "task.latest"], + server: "Pin / unpin thread · archive", + local: "Sort choice · collapsed groups", + copy: "Pinning and ordering are thread metadata; the sidebar does not own conversation content.", + }, +} as const; +type ProjectionKey = keyof typeof projections; +type ScenarioKey = keyof typeof scenarios; +const initialProjection: ProjectionKey = "chat"; +const initialScenario: ScenarioKey = "active"; +--- + +
    +
    + Interactive projection lab · Chapter 31 +

    One canonical thread, six product surfaces

    +

    Change the durable scenario, then choose a projection to see what it reads, leaves out, and can mutate.

    +
    + +
    + + + +
    + +

    {scenarios[initialScenario].label} · {projections[initialProjection].label}

    + +
    +
    Canonical threadthread_31 / durable fields
    +
    + {scenarios[initialScenario].fields.map((field) => {field})} +
    +

    {scenarios[initialScenario].note}

    +
    + +
    + {Object.entries(projections).map(([key, projection], index) => ( + + ))} +
    + +
    +
    {projections[initialProjection].label}{projections[initialProjection].copy}
    +
    +

    Consumes

      {projections[initialProjection].consumes.map((field) =>
    • {field}
    • )}
    +

    Intentionally suppresses

      {projections[initialProjection].suppresses.map((field) =>
    • {field}
    • )}
    +
    +
    Server-state controls{projections[initialProjection].server}
    Local-view controls{projections[initialProjection].local}
    +
    + +
    + Static projection map + + + {Object.entries(projections).map(([, projection]) => )} +
    SurfaceCanonical fields it consumesLocal view state
    {projection.label}{projection.consumes.join(" · ")}{projection.local}
    +
    + +
    + + + + diff --git a/src/components/TraceLab.astro b/src/components/TraceLab.astro new file mode 100644 index 0000000..bad50ae --- /dev/null +++ b/src/components/TraceLab.astro @@ -0,0 +1,158 @@ +--- +import { getSourceReference, sourceReferenceHref, sourceReferenceLabel } from "../lib/sources"; + +interface Step { stage: string; title: string; detail: string; sourceId?: string; } +interface Props { id: string; steps: Step[]; label?: string; prompt?: string; } +const { id, steps, label = "End-to-end request trace", prompt = "Move through the ordered stages or play the trace once." } = Astro.props; +if (steps.length === 0) throw new Error("TraceLab requires at least one step."); +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) throw new Error(`TraceLab '${label}' requires a stable kebab-case id.`); +const resolvedSteps = steps.map(({ sourceId, ...step }) => { + if (!sourceId) return step; + const reference = getSourceReference(sourceId); + return { + ...step, + source: sourceReferenceLabel(reference), + sourceHref: sourceReferenceHref(reference), + }; +}); +const payload = JSON.stringify(resolvedSteps).replaceAll("<", "\\u003c"); +--- + +
    +
    Interactive trace

    {label}

    {prompt}

    +
    + + + + 1 / {steps.length} +
    + +
      + {resolvedSteps.map((step, index) =>
    1. )} +
    +

    Step 1 of {steps.length}: {resolvedSteps[0]?.stage}

    +
    + {resolvedSteps[0]?.stage} +

    {resolvedSteps[0]?.title}

    +

    {resolvedSteps[0]?.detail}

    + +
    + +
      + {resolvedSteps.map((step) => ( +
    1. + {step.stage} · {step.title} +

      {step.detail}

      + {step.source && {step.source}} +
    2. + ))} +
    +
    + + diff --git a/src/components/TurnLifecycleLab.astro b/src/components/TurnLifecycleLab.astro new file mode 100644 index 0000000..ff2d3d5 --- /dev/null +++ b/src/components/TurnLifecycleLab.astro @@ -0,0 +1,162 @@ +--- +interface Props { id: string } + +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("TurnLifecycleLab requires a stable kebab-case id."); +} +const labId = `turn-lifecycle-${id}`; +--- + +
    +
    + Interactive state-machine lab +

    One durable request, several live outcomes

    +

    Choose an illustrative control for the current teaching state. A step flashes once, then rests; this is neither a live provider simulator nor the server's complete legality matrix.

    +
    + +
    +
    +

    Current state

    +

    Resting

    +

    No active provider turn is projected. A new user message can create durable start intent.

    +
    + +
      +
    1. Restingno active turn
    2. +
    3. Startingintent awaits runtime
    4. +
    5. Runningcorrelated live turn
    6. +
    7. Approvalwaiting on a decision
    8. +
    9. Inputwaiting on answers
    10. +
    11. Interruptedstop intent recorded
    12. +
    13. Readyturn ended
    14. +
    15. Errornew intent required
    16. +
    + +
    +

    Durable record

    Nothing new is being committed for this simulated turn.

    +

    Hot provider liveness

    No provider liveness is claimed.

    +
    + +
    +

    Teaching paths

    +
    +
    +
    + +

    State is Resting.

    + + +
    + Static transition table and boundary notes +
    + + + + + + + + + + +
    StateIllustrative controlsDurable meaningHot meaning
    Resting / ready / errorStart a new intentnew user message + start request + receipt can commitno provider start is proven yet
    StartingProvider starts; interruptpending start/session projection can be presentreactor may be preparing or sending
    RunningStream; request approval; request input; steer*; interrupt; complete; failcorrelated runtime facts can update session/messagesprovider liveness remains hot
    Approval / inputRespond; interruptpending request is visible; the turn can remain runningprovider waits for a response
    InterruptedStart a new intenta matching projected turn can be marked interruptednative abortion or session-state facts may still arrive later
    Completed / readyStart a new intentcompletion may settle session; checkpoint is separatenative session may still exist or later exit
    +
    +

    * “Steer” is provider-specific. The generic adapter contract has no steer method; this lab models its guarded superseding-turn case. The table is intentionally selective: the start decider itself does not enforce a “must be ready” state guard.

    +
    +
    + + + + diff --git a/src/components/UsageAccountingLab.astro b/src/components/UsageAccountingLab.astro new file mode 100644 index 0000000..8aa625d --- /dev/null +++ b/src/components/UsageAccountingLab.astro @@ -0,0 +1,259 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("UsageAccountingLab requires a stable kebab-case id."); +} + +const rows = [ + { file: "claude/a.jsonl", record: "C-1a", provider: "Claude", key: "m-1:r-1", tokens: 160, state: "first copy" }, + { file: "claude/a.jsonl", record: "C-1b", provider: "Claude", key: "m-1:r-1", tokens: 160, state: "within-file duplicate" }, + { file: "claude/b.jsonl", record: "C-1c", provider: "Claude", key: "m-1:r-1", tokens: 160, state: "cross-file copy" }, + { file: "codex/x.jsonl", record: "X-1", provider: "Codex", key: "none · parser-local suppression", tokens: 58, state: "distinct record" }, +]; +const labId = `usage-accounting-${id}`; +--- + +
    +
    + Interactive accounting laboratory +

    A file-derived total is built in stages

    +

    Move through the historical lane. The live context sample stays visible as a deliberately excluded operational signal.

    +
    + +
    + Live lane, not an input: thread T-9 currently reports 88,000 / 200,000 context tokens. It changes the composer meter only; it contributes 0 tokens and $0 to the historical total below. +
    + +
    + + + + + + +
    + + + +
    +

    Stage 1 of 6 · parse records

    +

    Four candidate records arrive from three files

    +

    The scanner streams provider JSONL. These are candidate usage records, not yet a total.

    +
    + + + + {rows.map((row) => )} + +
    FileRecordDedupe identityTokensStatus
    {row.file}{row.record}{row.key}{row.tokens}{row.state}
    +
    +
    +
    Candidate tokens
    538
    +
    Historical total
    not calculated
    +
    Live meter input
    excluded
    +
    +
    + +
    +

    Formulas used by the lab

    +

    processed = uncached input + cached input + cache creation + output

    +

    cost = uncached×inputRate + cached×cacheReadRate + creation×creationRate + output×outputRate

    +

    historical total = Σ kept, in-range records after source-fingerprint ownership

    +

    reasoning ⊆ output; do not add it a second time

    +
    + +
    + Static walkthrough and no-JavaScript reference +
      +
    1. Parse. Candidate rows total 538 tokens: three 160-token Claude copies and one 58-token Codex record.
    2. +
    3. Normalize. Claude's usage maps to 100 uncached + 30 cached + 10 creation + 20 output = 160. Codex's input includes cache, so it maps to 40 uncached + 10 cached + 0 creation + 8 output = 58.
    4. +
    5. Within-file dedupe. Keep C-1a; drop C-1b, which repeats the same Claude message/request key in a.jsonl.
    6. +
    7. Cross-file dedupe. Keep the first surviving Claude key; drop C-1c from the copied/resumed file. Codex has no global key here: its parser-local delta/fork suppression has already accepted distinct record X-1. The subtotal is 218 tokens.
    8. +
    9. Bucket and price. Place the two retained records in their day/provider/model buckets. The displayed formula applies model rates only when no finite provider-reported cost exists; price provenance remains part of the result.
    10. +
    11. Merge environments. Environment A owns the Claude source fingerprint. Environment B reports the identical fingerprint and is a shadow copy, so its Claude bucket is excluded. Environment C owns a different Codex fingerprint. The merged historical total remains 218 tokens.
    12. +
    +

    Still excluded: the live 88,000 / 200,000 thread context snapshot. It answers a capacity question, not this historical file-accounting question.

    +
    +
    + + + + diff --git a/src/components/WorkLogLab.astro b/src/components/WorkLogLab.astro new file mode 100644 index 0000000..b328024 --- /dev/null +++ b/src/components/WorkLogLab.astro @@ -0,0 +1,68 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) throw new Error("WorkLogLab requires a stable kebab-case id."); +const views = { + web: { label: "Web · chat work log", lead: "Illustrative projection, not live data: a quiet parent narrative collapses agent lifecycle into a spawn-batch call to action.", rows: [["Parent", "thread.message-sent", "durable thread narrative"], ["Spawn batch", "direct agents", "grouped by spawn turn"], ["Spawn batch", "workflow members", "grouped under the coordinator; CTA opens Agents"]], note: "Web's separate Agents surface carries detailed per-agent state. Progress and usage use stable latest-state streams, but the parent log is not one row per task." }, + agents: { label: "Web · Agents panel", lead: "Illustrative projection, not live data: a derived roster updates retained agent state in place.", rows: [["Agent", "task.progress", "working state when the payload identifies an agent"], ["Agent", "task.updated", "idle is resumable when reported"], ["Workflow", "task progress", "provider-derived members when present"]], note: "Token, tool, and duration fields are task-local rollups only when typed usage supplies them. They are not Chapter 20 totals." }, + mobile: { label: "Mobile · thread work log", lead: "Illustrative projection, not live data: compact rows keep a terminal signal because this path has no matching Agents roster.", rows: [["Work log", "task.completed", "terminal agent signal"], ["Work log", "terminal task.updated", "Codex child terminal signal"], ["Work log", "retained activity", "only source-backed activity is shown"]], note: "A mobile work log derives from the same activities; it does not create a mobile-only task store." }, +} as const; +const initial = views.web; +const labId = `work-log-${id}`; +const payload = JSON.stringify({ views }).replaceAll("<", "\\u003c"); +--- + +
    +
    Interactive work-log projector

    One thread, three surface projections

    Switch views to see what a surface may derive from durable thread activity without inventing a scheduler record.

    +
    {Object.entries(views).map(([key, view], index) => )}
    +

    {initial.label}. {initial.lead}

    +
    +
    {initial.label}thread: durable

    {initial.lead}

    +
      {initial.rows.map(([kind, title, detail]) =>
    1. {kind}
      {title}{detail}
    2. )}
    + +
    +
    Durable threadmessages · activities · lifecycle overlays
    Derived rostertask/subagent fold when evidence exists
    Ephemeral live stateliveness clears on restart/session death; plan progress clears at settlement/session death
    +
    Static projection rules
    • Web chat groups agent lifecycle into spawn-batch CTAs that open Agents: direct agents by spawn turn, workflow members by coordinator.
    • Web Agents renders a derived roster, including task-local typed usage when supplied.
    • Mobile retains compact terminal/task signals because this path has no equivalent Agents roster.
    • Pin, snooze, and lifecycle organize the thread; they do not schedule provider tasks.
    + + +
    + + + + diff --git a/src/components/WorkbenchCapabilityLab.astro b/src/components/WorkbenchCapabilityLab.astro new file mode 100644 index 0000000..6bc6153 --- /dev/null +++ b/src/components/WorkbenchCapabilityLab.astro @@ -0,0 +1,176 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("WorkbenchCapabilityLab requires a stable kebab-case id."); +} + +const services = { + terminal: { + label: "Terminal", + owner: "Server PTY manager", + transport: "RPC command + attach stream", + path: ["Client names thread + terminal id", "Server opens or restores PTY history", "Attach receives snapshot, then live output / exit / activity events"], + boundary: "The client renders a terminal; the process and its environment stay with the server.", + surfaces: { web: "Ghostty web surface", desktop: "web renderer inside Electron", mobile: "native terminal surface", provider: "No provider terminal endpoint" }, + }, + files: { + label: "Files", + owner: "Server workspace services", + transport: "Authenticated project RPC", + path: ["Client asks for bounded entries, search, read, or write", "Server resolves the workspace operation", "Client renders a tree, source/file preview, or editor state"], + boundary: "A file pane is not a local filesystem mirror; operations address the selected server environment.", + surfaces: { web: "tree, preview, and editor paths", desktop: "same web renderer path", mobile: "tree and file-preview paths", provider: "Provider tools are a separate harness contract" }, + }, + assets: { + label: "Assets", + owner: "Server asset access", + transport: "RPC URL issue → signed HTTP GET", + path: ["Client requests a URL for an attachment, workspace file, or favicon", "Server validates scope/type and signs expiring claims", "Browser or native image/web view fetches the relative asset URL"], + boundary: "A signed URL grants only the claimed resource/path until expiry; it is not a filesystem browse token.", + surfaces: { web: "uses shared asset URL state", desktop: "uses the web renderer path", mobile: "workspace-file asset hook", provider: "May receive attachment paths through its own adapter flow" }, + }, + preview: { + label: "Preview & browser", + owner: "Desktop Electron host + server preview metadata", + transport: "Server RPC/event model + desktop IPC/webview", + path: ["Server records per-thread tab metadata and revisions", "Desktop renderer requests actions through curated preload IPC; Electron's preview manager owns the guest Chromium WebContents", "Status/navigation are reported back and fan out to subscribers"], + boundary: "The server tracks collaboration state; it does not itself render or automate a browser page.", + surfaces: { web: "explicitly unavailable", desktop: "native webview host", mobile: "no matching in-app browser host", provider: "can request automation only through an available desktop host" }, + }, + mcp: { + label: "MCP preview toolkit", + owner: "Provider-session credential registry + MCP HTTP server", + transport: "Provider-scoped bearer HTTP + broker stream", + path: ["Provider service optionally issues one thread-scoped credential carrying a registry-generated MCP session id", "Provider adapter receives t3-code MCP configuration", "MCP request is authenticated, scoped, then brokered to a compatible desktop host"], + boundary: "This is T3's preview toolkit, not a universal inventory or controller for every MCP server a provider may know.", + surfaces: { web: "not an automation host", desktop: "can register an automation host", mobile: "not an automation host", provider: "uses t3-code only when the session is configured and authorized" }, + }, + vcs: { + label: "VCS & worktrees", + owner: "Server VCS driver", + transport: "Authenticated RPC commands and snapshots", + path: ["Client selects a project/thread workspace", "Server driver reads Git/VCS state or performs a requested operation", "Clients render the returned state; worktree creation remains a server-side saga"], + boundary: "VCS capability is environment-local. A UI view is not a promise that a remote checkout, branch, or worktree exists everywhere.", + surfaces: { web: "server-backed source-control views", desktop: "same web renderer path", mobile: "server-backed VCS state/actions", provider: "provider changes files through its own session cwd" }, + }, + pullRequests: { + label: "Pull requests", + owner: "Server host-provider service", + transport: "RPC controls + authenticated HTTP diff slices", + path: ["Web selects a capable environment and repository", "Server validates project/host/capability and fresh viewer permissions for writes", "Large diff slices travel over HTTP; mutations invalidate server-side listing epochs"], + boundary: "A visible action is never the authorization decision. The server re-checks host capability and current viewer permission before writes.", + surfaces: { web: "dedicated capability-gated route", desktop: "same web renderer route", mobile: "no matching pull-request route in this pinned mobile source audit", provider: "No provider turn-control path implied" }, + }, +} as const; + +const serviceEntries = Object.entries(services); +const initialKey = "terminal" as const; +const initial = services[initialKey]; +const labId = `workbench-capability-${id}`; +const payload = JSON.stringify({ services }).replaceAll("<", "\\u003c"); +--- + +
    +
    + Interactive capability and path matrix +

    Choose a workbench service; then inspect its owner, transport, and surface edge

    +

    Each path is an architecture summary of the pinned source, not a live T3 environment.

    +
    + +
    + {serviceEntries.map(([key, service], index) => ( + + ))} +
    + +
    +

    {initial.label}. {initial.owner}. {initial.transport}.

    +
    + {initial.label} +
    +
    Primary owner
    {initial.owner}
    +
    Transport model
    {initial.transport}
    +
    +
    +
      + {initial.path.map((step, index) =>
    1. {index + 1}{step}
    2. )} +
    + +
    +

    Surface edge

    +
    + {Object.entries(initial.surfaces).map(([surface, detail]) =>
    {surface === "provider" ? "Provider" : surface}
    {detail}
    )} +
    +
    +
    + +
    + Static matrix and reading rules +
    + + + {serviceEntries.map(([, service]) => )} +
    ServiceOwnerTransportImportant edge
    {service.label}{service.owner}{service.transport}{service.boundary}
    +
    +

    “Desktop uses the web renderer path” does not erase Electron-only authority: preview’s actual webview and automation host are desktop-owned. “No matching route” records this source audit; it is not a product roadmap claim.

    +
    + + +
    + + + + diff --git a/src/components/WorktreeTopologyLab.astro b/src/components/WorktreeTopologyLab.astro new file mode 100644 index 0000000..bc42757 --- /dev/null +++ b/src/components/WorktreeTopologyLab.astro @@ -0,0 +1,58 @@ +--- +interface Props { id: string; } +const { id } = Astro.props; +if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) { + throw new Error("WorktreeTopologyLab requires a stable kebab-case id."); +} +const labId = `worktree-topology-${id}`; +const modes = [ + { label: "Local request: no new worktree", nodes: ["No Git worktree creation", "Stored thread path, if present", "Otherwise project root", "Thread runs there"], detail: "This mode creates no linked worktree. A newly local thread commonly runs at the project root, but a local request can retain an already-selected workspace path; runtime resolution uses that stored thread path before the project root.", recovery: "If the path is not a Git repository, this is the only effective thread workspace mode. “Local” describes creation, not a ban on an existing workspace path." }, + { label: "New worktree from local base", nodes: ["Project root", "Chosen local base", "New branch + linked worktree", "Thread runs in linked tree"], detail: "The bootstrap asks Git to create a new branch at the selected base and checks it out in a separate path. The thread is then updated with that branch and worktree path.", recovery: "A Git creation failure aborts the bootstrap; the server cleans up a thread it created during that bootstrap, but does not promise to remove every filesystem side effect Git may already have made." }, + { label: "New worktree from origin", nodes: ["Project root", "Fetch origin", "Resolve origin base commit", "New branch + linked worktree", "Thread runs in linked tree"], detail: "When the option is enabled and origin exists, T3 fetches origin and resolves the requested base to a remote-tracking commit before creating the local branch/worktree.", recovery: "If origin is absent, the bootstrap falls back to the local selected base instead of failing solely because origin is unavailable." }, + { label: "Delete thread + optional orphan cleanup", nodes: ["Durably delete thread", "Stop provider + close terminal history", "Offer worktree cleanup when orphaned", "Forced Git removal only if confirmed"], detail: "Thread deletion is not a worktree deletion. The server stops the provider session and closes terminal history; the web client may then offer to force-remove a worktree only when this was its sole linked thread and a local API is available.", recovery: "If the optional Git removal or refresh fails, the thread remains deleted and the worktree can remain. The web client surfaces that partial failure for inspection or later cleanup." }, + { label: "Remove linked worktree", nodes: ["Project root", "Target linked path", "git worktree remove", "Path no longer present"], detail: "Removal calls Git with the selected linked path. The optional force flag is forwarded only when requested.", recovery: "Git remains the authority: a dirty or otherwise protected worktree can make removal fail, so inspect its state before retrying or forcing cleanup." }, +]; +const payload = JSON.stringify(modes).replaceAll("<", "\\u003c"); +--- + +
    +
    Animated topology lab

    Choose where a thread will run

    Each activation advances only once. There is no autonomous playback: you control the topology and the motion.

    +
    + {modes.map((mode, index) => )} +
    +

    Selected topology: {modes[0].label}

    +
      {modes[0].nodes.map((node, index) =>
    1. {node}
    2. )}
    +

    {modes[0].label}

    {modes[0].detail}

    Recovery boundary: {modes[0].recovery}

    +
    All topology outcomes
      {modes.map((mode) =>
    1. {mode.label}

      {mode.detail}

      Recovery boundary: {mode.recovery}

    2. )}
    + + +
    + + + + diff --git a/src/content.config.ts b/src/content.config.ts new file mode 100644 index 0000000..8d3e0ad --- /dev/null +++ b/src/content.config.ts @@ -0,0 +1,27 @@ +import { defineCollection } from "astro:content"; +import { glob } from "astro/loaders"; +import { z } from "astro/zod"; + +const book = defineCollection({ + loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/content/book" }), + schema: z.object({ + slug: z.string(), + order: z.number().int().nonnegative(), + number: z.string().optional(), + kind: z.enum(["front", "chapter", "appendix"]), + part: z.string(), + partOrder: z.number().int().nonnegative(), + title: z.string(), + shortTitle: z.string().optional(), + summary: z.string(), + status: z.enum(["draft", "source-checked", "verified"]), + gates: z.array(z.enum(["sources", "links", "interaction", "editorial"])).default([]), + objectives: z.array(z.string()).default([]), + keywords: z.array(z.string()).default([]), + sourceAreas: z.array(z.string()).default([]), + visuals: z.array(z.string()).default([]), + updatedAt: z.coerce.date(), + }), +}); + +export const collections = { book }; diff --git a/src/generated/excerpts.json b/src/generated/excerpts.json new file mode 100644 index 0000000..f3625fc --- /dev/null +++ b/src/generated/excerpts.json @@ -0,0 +1,1842 @@ +{ + "architecture-boundary": { + "id": "architecture-boundary", + "path": "docs/internals/overview.md", + "start": 5, + "end": 28, + "language": "markdown", + "label": "The execution boundary", + "code": "T3 Code is a server runtime that owns agent sessions, workspaces, and version control, plus clients\n(web, desktop, mobile) that talk to it over one authenticated Effect RPC WebSocket. The server is the\nexecution boundary: every provider process, terminal, git operation, and filesystem read happens\nthere, never in the client.\n\n```\n┌────────────────────────────────────────────────┐\n│ Clients: apps/web, apps/desktop, apps/mobile │\n│ shared runtime: packages/client-runtime │\n│ connection supervisor, RPC session, Atom state│\n└──────────────────┬─────────────────────────────┘\n │ Effect RPC over WebSocket (/ws)\n │ contract: packages/contracts\n┌──────────────────▼─────────────────────────────┐\n│ apps/server │\n│ orchestration engine (event-sourced) │\n│ provider driver registry (5 built-in drivers) │\n│ checkpointing, VCS, terminals, filesystem │\n└──────────────────┬─────────────────────────────┘\n │ per-driver transport\n┌──────────────────▼─────────────────────────────┐\n│ Agent CLIs: Codex, Claude, Cursor, Grok, │\n│ OpenCode │\n└────────────────────────────────────────────────┘", + "checksum": "fd6effc6bfb1e04275e59190badc87399e6298b077fe3d05e7eb0f8544afd698" + }, + "orchestration-rpc-methods": { + "id": "orchestration-rpc-methods", + "path": "packages/contracts/src/orchestration.ts", + "start": 27, + "end": 36, + "language": "typescript", + "label": "Orchestration RPC surface", + "code": "export const ORCHESTRATION_WS_METHODS = {\n dispatchCommand: \"orchestration.dispatchCommand\",\n getWorkflowScript: \"orchestration.getWorkflowScript\",\n getTurnDiff: \"orchestration.getTurnDiff\",\n getFullThreadDiff: \"orchestration.getFullThreadDiff\",\n searchThreads: \"orchestration.searchThreads\",\n getArchivedShellSnapshot: \"orchestration.getArchivedShellSnapshot\",\n subscribeShell: \"orchestration.subscribeShell\",\n subscribeThread: \"orchestration.subscribeThread\",\n} as const;", + "checksum": "654f6e0acadb65856a7b1267a314ba5d501fdb7bb2b44847ec54d2a77e034e7c" + }, + "turn-start-command": { + "id": "turn-start-command", + "path": "packages/contracts/src/orchestration.ts", + "start": 847, + "end": 864, + "language": "typescript", + "label": "Client turn-start command", + "code": "const ClientThreadTurnStartCommand = Schema.Struct({\n type: Schema.Literal(\"thread.turn.start\"),\n commandId: CommandId,\n threadId: ThreadId,\n message: Schema.Struct({\n messageId: MessageId,\n role: Schema.Literal(\"user\"),\n text: Schema.String,\n attachments: Schema.Array(UploadChatAttachment),\n }),\n modelSelection: Schema.optional(ModelSelection),\n titleSeed: Schema.optional(TrimmedNonEmptyString),\n runtimeMode: RuntimeMode,\n interactionMode: ProviderInteractionMode,\n bootstrap: Schema.optional(ThreadTurnStartBootstrap),\n sourceProposedPlan: Schema.optional(SourceProposedPlanReference),\n createdAt: IsoDateTime,\n});", + "checksum": "2a356b9b8badac1a1eda578900fc6847c5095057aaa4bc34c9ab057b352c64ec" + }, + "provider-adapter-core": { + "id": "provider-adapter-core", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 47, + "end": 71, + "language": "typescript", + "label": "Provider adapter lifecycle contract", + "code": "export interface ProviderAdapterShape {\n /**\n * Provider kind implemented by this adapter.\n */\n readonly provider: ProviderDriverKind;\n readonly capabilities: ProviderAdapterCapabilities;\n\n /**\n * Start a provider-backed session.\n */\n readonly startSession: (\n input: ProviderSessionStartInput,\n ) => Effect.Effect;\n\n /**\n * Send a turn to an active provider session.\n */\n readonly sendTurn: (\n input: ProviderSendTurnInput,\n ) => Effect.Effect;\n\n /**\n * Interrupt an active turn.\n */\n readonly interruptTurn: (threadId: ThreadId, turnId?: TurnId) => Effect.Effect;", + "checksum": "a75847d120df17015de3fdcd97ab0f5a3b5d3f7c8b19f950e0c0d484441e17cf" + }, + "provider-adapter-interactions": { + "id": "provider-adapter-interactions", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 73, + "end": 94, + "language": "typescript", + "label": "Provider approval and input contract", + "code": " /**\n * Respond to an interactive approval request.\n */\n readonly respondToRequest: (\n threadId: ThreadId,\n requestId: ApprovalRequestId,\n decision: ProviderApprovalDecision,\n ) => Effect.Effect;\n\n /**\n * Respond to a structured user-input request.\n */\n readonly respondToUserInput: (\n threadId: ThreadId,\n requestId: ApprovalRequestId,\n answers: ProviderUserInputAnswers,\n ) => Effect.Effect;\n\n /**\n * Stop one provider session.\n */\n readonly stopSession: (threadId: ThreadId) => Effect.Effect;", + "checksum": "67b4610571f49faa99826588c7af37dafaf379bc25f4e9d012a429cc31f5858d" + }, + "provider-adapter-stream": { + "id": "provider-adapter-stream", + "path": "apps/server/src/provider/Services/ProviderAdapter.ts", + "start": 126, + "end": 134, + "language": "typescript", + "label": "Canonical provider event stream", + "code": " /**\n * Stop all sessions owned by this adapter.\n */\n readonly stopAll: () => Effect.Effect;\n\n /**\n * Canonical runtime event stream emitted by this adapter.\n */\n readonly streamEvents: Stream.Stream;", + "checksum": "4a95ebce476cfbf3fd22ef7f508d1ef5b55ac49db91548ed4b3ab8fdd482d443" + }, + "orchestration-transaction": { + "id": "orchestration-transaction", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 197, + "end": 259, + "language": "typescript", + "label": "Atomic command commit", + "code": " const committedCommand = yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const committedEvents: OrchestrationEvent[] = [];\n let nextCommandReadModel = commandReadModel;\n\n for (const nextEvent of eventBases) {\n const savedEvent = yield* eventStore.append(nextEvent);\n nextCommandReadModel = yield* projectEvent(nextCommandReadModel, savedEvent);\n yield* projectionPipeline.projectEvent(savedEvent);\n committedEvents.push(savedEvent);\n }\n\n const lastSavedEvent = committedEvents.at(-1) ?? null;\n if (lastSavedEvent === null) {\n return yield* new OrchestrationCommandInvariantError({\n commandType: envelope.command.type,\n detail: \"Command produced no events.\",\n });\n }\n\n yield* commandReceiptRepository.upsert({\n commandId: envelope.command.commandId,\n aggregateKind: lastSavedEvent.aggregateKind,\n aggregateId: lastSavedEvent.aggregateId,\n acceptedAt: lastSavedEvent.occurredAt,\n resultSequence: lastSavedEvent.sequence,\n status: \"accepted\",\n error: null,\n });\n\n return {\n committedEvents,\n lastSequence: lastSavedEvent.sequence,\n nextCommandReadModel,\n } as const;\n }),\n )\n .pipe(\n Effect.catchTag(\"SqlError\", (sqlError) =>\n Effect.fail(\n toPersistenceSqlError(\"OrchestrationEngine.processEnvelope:transaction\")(sqlError),\n ),\n ),\n );\n\n commandReadModel = committedCommand.nextCommandReadModel;\n for (const [index, event] of committedCommand.committedEvents.entries()) {\n yield* PubSub.publish(eventPubSub, event);\n if (index === 0) {\n yield* Metric.update(\n Metric.withAttributes(\n orchestrationCommandAckDuration,\n metricAttributes({\n ...baseMetricAttributes,\n ackEventType: event.type,\n }),\n ),\n Duration.millis(Math.max(0, (yield* Clock.currentTimeMillis) - envelope.startedAtMs)),\n );\n }\n }\n return { sequence: committedCommand.lastSequence };", + "checksum": "24e00da0c432e501172e3847817fde311d8656b07e3b8261c657ecf6b4c35d4c" + }, + "orchestration-dispatch": { + "id": "orchestration-dispatch", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 331, + "end": 368, + "language": "typescript", + "label": "Serialized command dispatch and event fan-out", + "code": " yield* projectionPipeline.bootstrap;\n commandReadModel = yield* projectionSnapshotQuery.getCommandReadModel();\n\n const worker = Effect.forever(Queue.take(commandQueue).pipe(Effect.flatMap(processEnvelope)));\n yield* Effect.forkScoped(worker);\n yield* Effect.logDebug(\"orchestration engine started\").pipe(\n Effect.annotateLogs({ sequence: commandReadModel.snapshotSequence }),\n );\n\n const readEvents: OrchestrationEngineShape[\"readEvents\"] = (fromSequenceExclusive, limit) =>\n eventStore.readFromSequence(fromSequenceExclusive, limit);\n\n const dispatch: OrchestrationEngineShape[\"dispatch\"] = (command, options) =>\n Effect.gen(function* () {\n const result = yield* Deferred.make<{ sequence: number }, OrchestrationDispatchError>();\n yield* Queue.offer(commandQueue, {\n command,\n origin: options?.origin,\n result,\n startedAtMs: yield* Clock.currentTimeMillis,\n });\n return yield* Deferred.await(result);\n });\n\n return {\n readEvents,\n dispatch,\n // Each access creates a fresh PubSub subscription so that multiple\n // consumers (wsServer, ProviderRuntimeIngestion, CheckpointReactor, etc.)\n // each independently receive all domain events.\n get streamDomainEvents(): OrchestrationEngineShape[\"streamDomainEvents\"] {\n return Stream.fromPubSub(eventPubSub);\n },\n // The command read model's snapshotSequence tracks the latest committed\n // event sequence (updated on the worker fiber). A plain property read is a\n // consistent, committed value — reassignment of `commandReadModel` is\n // atomic on the single-threaded event loop.\n latestSequence: Effect.sync(() => commandReadModel.snapshotSequence),", + "checksum": "85e20350d344ef6e865480addc97f37638fb833acbee999092d2a1b537019bfa" + }, + "server-runtime-core": { + "id": "server-runtime-core", + "path": "apps/server/src/server.ts", + "start": 353, + "end": 416, + "language": "typescript", + "label": "Authentication, remote endpoint, provider, and server dependency assembly", + "code": "const AuthLayerLive = EnvironmentAuth.layer.pipe(\n Layer.provideMerge(PersistenceLayerLive),\n Layer.provide(ServerSecretStore.layer),\n);\n\nconst CloudManagedEndpointRuntimeLive = Layer.mergeAll(\n RelayClientLive,\n CloudManagedEndpointRuntime.layer.pipe(\n Layer.provide(ServerSecretStore.layer),\n Layer.provide(RelayClientLive),\n ),\n);\n\nconst ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(\n Layer.provideMerge(ProviderLayerLive),\n Layer.provideMerge(OrchestrationLayerLive),\n);\n\nconst RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(\n // Core Services\n Layer.provideMerge(ServerSettingsLayerLive),\n Layer.provideMerge(CheckpointingLayerLive),\n Layer.provideMerge(SourceControlProviderRegistryLayerLive),\n Layer.provideMerge(GitLayerLive),\n Layer.provideMerge(VcsLayerLive),\n Layer.provideMerge(ProviderRuntimeLayerLive),\n Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)),\n Layer.provideMerge(PersistenceLayerLive),\n Layer.provideMerge(Keybindings.layer),\n Layer.provideMerge(ProviderRegistryLive),\n // The instance registry is the new routing keystone — text generation,\n // adapter lookup, and runtime ingestion all resolve `ProviderInstanceId`\n // through this layer. Built-in drivers come from `BUILT_IN_DRIVERS`;\n // `providerInstances` hydration merges `settings.providers.`\n // with explicit `providerInstances` entries on boot.\n Layer.provideMerge(ProviderInstanceRegistryHydrationLive),\n // Shared native/canonical NDJSON writers used by both the per-instance\n // drivers (native stream, written from inside each `Adapter`) and\n // `ProviderService` (canonical stream, written after event normalization).\n // Provided once at the runtime level so every consumer sees the same\n // logger instances.\n Layer.provideMerge(ProviderEventLoggers.layer),\n // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old\n // `ProviderRegistryLive` pulled `OpenCodeRuntimeLive` in for itself, but\n // the rewritten registry reads snapshots off the instance registry and\n // no longer transitively provides it. Exposing it at the runtime level\n // keeps a single Live for all opencode consumers.\n Layer.provideMerge(OpenCodeRuntime.OpenCodeRuntimeLive),\n Layer.provideMerge(WorkspaceLayerLive),\n Layer.provideMerge(ProjectFaviconResolverLayerLive),\n Layer.provideMerge(RepositoryIdentityResolver.layer),\n Layer.provideMerge(ServerEnvironment.layer),\n Layer.provideMerge(AuthLayerLive),\n Layer.provideMerge(ServerSecretStore.layer),\n Layer.provideMerge(\n Layer.mergeAll(\n CloudCliTokenManager.layer.pipe(\n Layer.provide(ServerSecretStore.layer),\n Layer.provide(ExternalLauncher.layer),\n ),\n CloudManagedEndpointRuntimeLive,\n ),\n ),\n);", + "checksum": "11cc88459d4db7e4b29b6b738dcdaba486d8385f6cec6e7dde0d7851c7ada9c5" + }, + "dispatch-result": { + "id": "dispatch-result", + "path": "packages/contracts/src/orchestration.ts", + "start": 1580, + "end": 1583, + "language": "typescript", + "label": "Successful client dispatch result", + "code": "export const DispatchResult = Schema.Struct({\n sequence: NonNegativeInt,\n});\nexport type DispatchResult = typeof DispatchResult.Type;", + "checksum": "151b83cdd47b9a449a38bb64d9f7b37ccd31ab6f109753cb6535214e12bf98de" + }, + "rejected-receipt-best-effort": { + "id": "rejected-receipt-best-effort", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 287, + "end": 325, + "language": "typescript", + "label": "Best-effort invariant-rejection receipt", + "code": " if (Exit.isSuccess(exit)) {\n yield* Deferred.succeed(envelope.result, exit.value);\n return;\n }\n\n const error = Cause.squash(exit.cause) as OrchestrationDispatchError;\n if (\n !isOrchestrationCommandPreviouslyRejectedError(error) &&\n !isOrchestrationCommandIdConflictError(error)\n ) {\n yield* reconcileReadModelAfterDispatchFailure.pipe(\n Effect.catch(() =>\n Effect.logWarning(\n \"failed to reconcile orchestration read model after dispatch failure\",\n ).pipe(\n Effect.annotateLogs({\n commandId: envelope.command.commandId,\n snapshotSequence: commandReadModel.snapshotSequence,\n }),\n ),\n ),\n );\n\n if (isOrchestrationCommandInvariantError(error)) {\n yield* commandReceiptRepository\n .upsert({\n commandId: envelope.command.commandId,\n aggregateKind: aggregateRef.aggregateKind,\n aggregateId: aggregateRef.aggregateId,\n acceptedAt: yield* nowIso,\n resultSequence: commandReadModel.snapshotSequence,\n status: \"rejected\",\n error: error.message,\n })\n .pipe(Effect.catch(() => Effect.void));\n }\n }\n\n yield* Deferred.fail(envelope.result, error);", + "checksum": "baa86ecd4a4a583386c539189ea6d26d3b4c6377201a660a9d22b2eb52a7645b" + }, + "hot-reactor-no-replay": { + "id": "hot-reactor-no-replay", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1405, + "end": 1409, + "language": "typescript", + "label": "Hot post-commit stream has no pending-work replay", + "code": " yield* forkParked(Stream.runForEach(orchestrationEngine.streamDomainEvents, processEvent));\n\n // The domain event stream is hot, so work pending before this reactor\n // starts cannot be resumed. Correlated completions only clear the request\n // captured here, leaving any newer request untouched.", + "checksum": "fe4e62df9690c497361768207b76ed48bb65364abc5ef5b123321deb6c0277ee" + }, + "cli-entry-command": { + "id": "cli-entry-command", + "path": "apps/server/src/bin.ts", + "start": 23, + "end": 71, + "language": "typescript", + "label": "Root CLI and subcommand dispatch", + "code": "const connectPublicConfigMissingMessage =\n \"T3 Connect commands are unavailable: this build is missing T3 Connect public configuration.\";\n\nclass ConnectPublicConfigMissingError extends CliError.UserError {\n override get message() {\n return connectPublicConfigMissingMessage;\n }\n}\n\nconst connectUnavailableCommand = Command.make(\"connect\", {\n command: Argument.string(\"command\").pipe(Argument.variadic),\n}).pipe(\n Command.withDescription(\"T3 Connect is unavailable in builds without public configuration.\"),\n Command.withHidden,\n Command.withHandler(() =>\n Effect.fail(\n new CliError.ShowHelp({\n commandPath: [\"t3\", \"connect\"],\n errors: [new ConnectPublicConfigMissingError({ cause: connectPublicConfigMissingMessage })],\n }),\n ),\n ),\n);\n\nexport const makeCli = ({ cloudEnabled = hasCloudPublicConfig } = {}) =>\n Command.make(\"t3\", { ...sharedServerCommandFlags }).pipe(\n Command.withDescription(\"Run the T3 Code server.\"),\n Command.withHandler((flags) => runServerCommand(flags)),\n Command.withSubcommands([\n startCommand,\n serveCommand,\n pairCommand,\n authCommand,\n projectCommand,\n serviceCommand,\n servicePreflightCommand,\n triageCommand,\n cloudEnabled ? connectCommand : connectUnavailableCommand,\n ]),\n );\n\nexport const cli = makeCli();\n\nif (import.meta.main) {\n Command.run(cli, { version: packageJson.version }).pipe(\n Effect.scoped,\n Effect.provide(CliRuntimeLayer),\n NodeRuntime.runMain,\n );", + "checksum": "4cbb1e2584966a2f8399dbdf57f860033d79e1da2aba843e49a008d4a4cdc2ab" + }, + "cli-config-precedence": { + "id": "cli-config-precedence", + "path": "apps/server/src/cli/config.ts", + "start": 244, + "end": 280, + "language": "typescript", + "label": "Mode, port, and base-directory precedence", + "code": " const mode: ServerConfig.RuntimeMode = Option.getOrElse(\n resolveOptionPrecedence(\n normalizedFlags.mode,\n Option.fromUndefinedOr(env.mode),\n Option.fromUndefinedOr(bootstrap?.mode),\n ),\n () => \"web\",\n );\n\n const port = yield* Option.match(\n resolveOptionPrecedence(\n normalizedFlags.port,\n Option.fromUndefinedOr(env.port),\n Option.fromUndefinedOr(bootstrap?.port),\n ),\n {\n onSome: (value) => Effect.succeed(value),\n onNone: () => {\n if (mode === \"desktop\") {\n return Effect.succeed(ServerConfig.DEFAULT_PORT);\n }\n return findAvailablePort(ServerConfig.DEFAULT_PORT);\n },\n },\n );\n const devUrl = Option.getOrElse(\n resolveOptionPrecedence(normalizedFlags.devUrl, Option.fromUndefinedOr(env.devUrl)),\n () => undefined,\n );\n const explicitBaseDir = resolveOptionPrecedence(\n normalizedFlags.baseDir,\n Option.fromUndefinedOr(env.t3Home),\n ).pipe(Option.filter((value) => value.trim().length > 0));\n const baseDir = yield* resolveBaseDir(\n Option.getOrUndefined(\n resolveOptionPrecedence(explicitBaseDir, Option.fromUndefinedOr(bootstrap?.t3Home)),\n ),", + "checksum": "f772af33c3c09ffd6b1641fe1391724758215ae054421feba0e93fc83f736d87" + }, + "cli-serve-semantics": { + "id": "cli-serve-semantics", + "path": "apps/server/src/cli/server.ts", + "start": 21, + "end": 35, + "language": "typescript", + "label": "Start and headless serve semantics", + "code": "export const startCommand = Command.make(\"start\", { ...sharedServerCommandFlags }).pipe(\n Command.withDescription(\"Run the T3 Code server.\"),\n Command.withHandler((flags) => runServerCommand(flags)),\n);\n\nexport const serveCommand = Command.make(\"serve\", { ...sharedServerCommandFlags }).pipe(\n Command.withDescription(\n \"Run the T3 Code server without opening a browser and print headless pairing details.\",\n ),\n Command.withHandler((flags) =>\n runServerCommand(flags, {\n startupPresentation: \"headless\",\n forceAutoBootstrapProjectFromCwd: false,\n }),\n ),", + "checksum": "114413115c5143f5873145eb904d38d5ad2b7316516f397de0514fa0b41d8bf8" + }, + "startup-readiness-order": { + "id": "startup-readiness-order", + "path": "apps/server/src/serverRuntimeStartup.ts", + "start": 514, + "end": 548, + "language": "typescript", + "label": "Prepared, activated, command-ready, and ready order", + "code": " yield* Effect.logDebug(\"startup phase: waiting for http listener\");\n yield* runStartupPhase(\"http.wait\", Deferred.await(httpListening));\n yield* runStartupPhase(\n \"auxiliary-roots.parked\",\n options?.awaitAuxiliaryParked ?? Effect.void,\n );\n\n // This is the prepared boundary. Every dependency has been acquired and\n // every runtime root has confirmed that it is parked before this request.\n const updateOutcome = yield* launcher.prepareTrial;\n yield* runStartupPhase(\n \"welcome.publish\",\n lifecycleEvents.publish({\n version: 1,\n type: \"welcome\",\n payload: { environment, ...welcomeBase },\n }),\n );\n yield* options?.activate ?? Effect.void;\n\n yield* Effect.logDebug(\"Accepting commands\");\n yield* commandGate.signalCommandReady;\n yield* runStartupPhase(\n \"ready.publish\",\n lifecycleEvents.publish({\n version: 1,\n type: \"ready\",\n payload: {\n at: DateTime.formatIso(yield* DateTime.now),\n environment,\n ...(updateOutcome === undefined ? {} : { updateOutcome }),\n },\n }),\n );\n yield* Effect.logDebug(\"startup phase: complete\");", + "checksum": "8ed6988b351036573a062e87716f4a1154d4d3e69710d8041f6b849965ced364" + }, + "command-readiness-middleware": { + "id": "command-readiness-middleware", + "path": "apps/server/src/server.ts", + "start": 431, + "end": 437, + "language": "typescript", + "label": "Global route-execution readiness barrier", + "code": "const commandReadinessLayer = HttpRouter.middleware(\n (httpEffect) =>\n Effect.flatMap(ServerRuntimeStartup.ServerRuntimeStartup, (startup) =>\n startup.awaitCommandReady.pipe(Effect.orDie, Effect.andThen(httpEffect)),\n ),\n { global: true },\n);", + "checksum": "656843f40a4ec8a4e2b1a5dca6671d9264c33edd92731693262a960972ff770f" + }, + "rpc-stream-contracts": { + "id": "rpc-stream-contracts", + "path": "packages/contracts/src/rpc.ts", + "start": 933, + "end": 948, + "language": "typescript", + "label": "Typed shell and thread streaming RPC contracts", + "code": "export const WsOrchestrationSubscribeShellRpc = Rpc.make(ORCHESTRATION_WS_METHODS.subscribeShell, {\n payload: OrchestrationRpcSchemas.subscribeShell.input,\n success: OrchestrationRpcSchemas.subscribeShell.output,\n error: Schema.Union([OrchestrationGetSnapshotError, EnvironmentAuthorizationError]),\n stream: true,\n});\n\nexport const WsOrchestrationSubscribeThreadRpc = Rpc.make(\n ORCHESTRATION_WS_METHODS.subscribeThread,\n {\n payload: OrchestrationRpcSchemas.subscribeThread.input,\n success: OrchestrationRpcSchemas.subscribeThread.output,\n error: Schema.Union([OrchestrationGetSnapshotError, EnvironmentAuthorizationError]),\n stream: true,\n },\n);", + "checksum": "efb34f4d793fed351ef25bd2e61b7c448bea8748c2edede590ba9a0f72336b0b" + }, + "thread-resume-race": { + "id": "thread-resume-race", + "path": "apps/server/src/ws.ts", + "start": 1394, + "end": 1521, + "language": "typescript", + "label": "Attach-before-read and bounded thread replay", + "code": " [ORCHESTRATION_WS_METHODS.subscribeThread]: (input) =>\n observeRpcStreamEffect(\n ORCHESTRATION_WS_METHODS.subscribeThread,\n Effect.gen(function* () {\n const isThisThreadDetailEvent = (event: OrchestrationEvent) =>\n event.aggregateKind === \"thread\" &&\n event.aggregateId === input.threadId &&\n isThreadDetailEvent(event);\n\n const liveStream = orchestrationEngine.streamDomainEvents.pipe(\n Stream.filter(isThisThreadDetailEvent),\n Stream.map((event) => ({\n kind: \"event\" as const,\n event: projectActivityEvent(event),\n })),\n );\n\n // Attach live delivery before reading either replay or snapshot state.\n // Otherwise an event published while the snapshot is loading is lost.\n const liveBuffer = yield* Queue.unbounded();\n yield* Effect.forkScoped(\n liveStream.pipe(Stream.runForEach((item) => Queue.offer(liveBuffer, item))),\n );\n const bufferedLiveStream = Stream.fromQueue(liveBuffer);\n\n // When the client already loaded the snapshot over HTTP it passes\n // that snapshot's sequence, and we resume the live subscription by\n // replaying persisted events after it instead of re-sending the\n // (potentially multi-KB) snapshot frame over the socket.\n //\n // The live PubSub subscription must be attached *before* draining\n // the catch-up replay, otherwise events published during the replay\n // window are dropped (they are past the persisted tail the replay\n // read, but the live stream is not yet subscribed). So fork the\n // live stream into a buffer bound to this stream's scope, then emit\n // catch-up followed by the buffered/ongoing live events. Overlapping\n // events are deduped by sequence on the client.\n //\n // The replay is bounded to the projection head captured below. The\n // catch-up range is normally tiny (a fresh HTTP snapshot sequence),\n // but a stale cached cursor can sit hundreds of thousands of global\n // events behind — replaying that decodes every intervening event\n // (including every other thread's tool payloads) only to discard\n // almost all of them, which has OOM-killed servers on large\n // databases. A truncated replay would silently drop this thread's\n // events, so past the gap cap we reset the client with a fresh\n // thread snapshot instead, exactly like subscribeShell above.\n if (input.afterSequence !== undefined) {\n const afterSequence = input.afterSequence;\n const headSequence = yield* orchestrationEngine.latestSequence;\n const replayGap = headSequence - afterSequence;\n if (replayGap >= 0 && replayGap <= THREAD_RESUME_MAX_GAP) {\n const catchUpStream = orchestrationEngine\n .readEvents(afterSequence, replayGap)\n .pipe(\n Stream.filter(isThisThreadDetailEvent),\n Stream.map((event) => ({\n kind: \"event\" as const,\n event: projectActivityEvent(event),\n })),\n Stream.mapError(\n (cause) =>\n new OrchestrationGetSnapshotError({\n message: `Failed to replay thread ${input.threadId} events`,\n cause,\n }),\n ),\n );\n const afterCatchUp =\n input.requestCompletionMarker === true\n ? Stream.concat(\n Stream.fromEffect(\n Queue.offer(liveBuffer, { kind: \"synchronized\" as const }),\n ).pipe(Stream.drain),\n bufferedLiveStream,\n )\n : bufferedLiveStream;\n return Stream.concat(catchUpStream, afterCatchUp);\n }\n // Gap too large (or cursor ahead of authoritative state): fall\n // through to the snapshot path so the client converges from a\n // fresh thread detail instead of an unbounded replay.\n }\n\n const snapshot = yield* projectionSnapshotQuery\n .getThreadDetailSnapshot(\n input.threadId,\n // Windowing the fallback snapshot is opt-in per subscription:\n // clients that don't send turnLimit (including all\n // pre-pagination clients) get the full thread, since they\n // have no way to load older pages.\n input.turnLimit === undefined ? undefined : { turnLimit: input.turnLimit },\n )\n .pipe(\n Effect.mapError(\n (cause) =>\n new OrchestrationGetSnapshotError({\n message: `Failed to load thread ${input.threadId}`,\n cause,\n }),\n ),\n );\n\n if (Option.isNone(snapshot)) {\n return yield* new OrchestrationGetSnapshotError({\n message: `Thread ${input.threadId} was not found`,\n cause: input.threadId,\n });\n }\n\n const afterSnapshot =\n input.requestCompletionMarker === true\n ? Stream.concat(\n Stream.fromEffect(\n Queue.offer(liveBuffer, { kind: \"synchronized\" as const }),\n ).pipe(Stream.drain),\n bufferedLiveStream,\n )\n : bufferedLiveStream;\n return Stream.concat(\n Stream.make({\n kind: \"snapshot\" as const,\n snapshot: projectThreadDetailSnapshot(snapshot.value),\n }),\n afterSnapshot,\n );\n }),\n { \"rpc.aggregate\": \"orchestration\" },", + "checksum": "0f57dcc6b6815e4cd36c8eca74f696252ba35e6d8446a41d66f413eb214f54f3" + }, + "auth-credential-precedence": { + "id": "auth-credential-precedence", + "path": "apps/server/src/auth/EnvironmentAuth.ts", + "start": 592, + "end": 632, + "language": "typescript", + "label": "Cookie, Bearer, and DPoP authentication precedence", + "code": " const authenticateRequest = (\n request: HttpServerRequest.HttpServerRequest,\n ): Effect.Effect => {\n const cookieToken = request.cookies[sessions.cookieName];\n const bearerToken = parseBearerToken(request);\n const dpopToken = parseDpopToken(request);\n const credential = cookieToken ?? bearerToken ?? dpopToken;\n if (!credential) {\n return Effect.fail(new ServerAuthMissingCredentialError({}));\n }\n return authenticateToken(credential).pipe(\n Effect.flatMap((session) => {\n if (session.proofKeyThumbprint) {\n if (!dpopToken || dpopToken !== credential) {\n return Effect.fail(\n new ServerAuthInvalidCredentialError({\n diagnostic: \"DPoP-bound access token requires DPoP authorization.\",\n }),\n );\n }\n return verifyRequestDpopProof({\n request,\n expectedThumbprint: session.proofKeyThumbprint,\n expectedAccessToken: dpopToken,\n }).pipe(\n Effect.provideService(ServerSecretStore.ServerSecretStore, secretStore),\n Effect.provideService(Crypto.Crypto, crypto),\n Effect.as(session),\n );\n }\n if (dpopToken) {\n return Effect.fail(\n new ServerAuthInvalidCredentialError({\n diagnostic: \"DPoP authorization requires a proof-bound access token.\",\n }),\n );\n }\n return Effect.succeed(session);\n }),\n );\n };", + "checksum": "d18c91b8d4ceaa79bc875630b87a342328ced1fc8a43556643ea32431af3232d" + }, + "websocket-ticket-verification": { + "id": "websocket-ticket-verification", + "path": "apps/server/src/auth/SessionStore.ts", + "start": 785, + "end": 851, + "language": "typescript", + "label": "WebSocket ticket verification reloads session state", + "code": " const verifyWebSocketToken: SessionStore[\"Service\"][\"verifyWebSocketToken\"] = Effect.fn(\n \"SessionStore.verifyWebSocketToken\",\n )(function* (token) {\n const [encodedPayload, signature] = token.split(\".\");\n if (!encodedPayload || !signature) {\n return yield* new MalformedWebSocketTokenError({});\n }\n\n const expectedSignature = signPayload(encodedPayload, signingSecret);\n if (!timingSafeEqualBase64Url(signature, expectedSignature)) {\n return yield* new InvalidWebSocketTokenSignatureError({});\n }\n\n const claims = yield* decodeWebSocketClaims(base64UrlDecodeUtf8(encodedPayload)).pipe(\n Effect.mapError((cause) => new InvalidWebSocketTokenPayloadError({ cause })),\n );\n\n const observedAt = yield* DateTime.now;\n const expiresAt = DateTime.make(claims.exp);\n if (Option.isNone(expiresAt)) {\n return yield* new InvalidSessionExpirationClaimError({\n sessionId: claims.sid,\n expirationClaim: claims.exp,\n });\n }\n if (claims.exp <= observedAt.epochMilliseconds) {\n return yield* new WebSocketTokenExpiredError({\n sessionId: claims.sid,\n expiresAt: expiresAt.value,\n observedAt,\n });\n }\n\n const row = yield* authSessions\n .getById({ sessionId: claims.sid })\n .pipe(\n Effect.mapError(\n (cause) => new WebSocketTokenVerificationError({ sessionId: claims.sid, cause }),\n ),\n );\n if (Option.isNone(row)) {\n return yield* new UnknownWebSocketSessionError({ sessionId: claims.sid });\n }\n if (row.value.expiresAt.epochMilliseconds <= observedAt.epochMilliseconds) {\n return yield* new WebSocketSessionExpiredError({\n sessionId: claims.sid,\n expiresAt: row.value.expiresAt,\n observedAt,\n });\n }\n if (row.value.revokedAt !== null) {\n return yield* new WebSocketSessionRevokedError({\n sessionId: claims.sid,\n revokedAt: row.value.revokedAt,\n });\n }\n\n return {\n sessionId: row.value.sessionId,\n token,\n method: row.value.method,\n client: toClientMetadata(row.value.client),\n expiresAt: row.value.expiresAt,\n subject: row.value.subject,\n scopes: row.value.scopes,\n } satisfies VerifiedSession;\n });", + "checksum": "dcb5b1a1fbdbcb3efae560e941aeed24343450e553fb345e55b71c1707bd0f9f" + }, + "command-union-boundary": { + "id": "command-union-boundary", + "path": "packages/contracts/src/orchestration.ts", + "start": 913, + "end": 1057, + "language": "typescript", + "label": "Client-dispatchable, normalized, and trusted internal command unions", + "code": "const DispatchableClientOrchestrationCommand = Schema.Union([\n ProjectCreateCommand,\n ProjectMetaUpdateCommand,\n ProjectDeleteCommand,\n ThreadCreateCommand,\n ThreadDeleteCommand,\n ThreadArchiveCommand,\n ThreadUnarchiveCommand,\n ThreadSettleCommand,\n ThreadUnsettleCommand,\n ThreadSnoozeCommand,\n ThreadUnsnoozeCommand,\n ThreadPinCommand,\n ThreadUnpinCommand,\n ThreadPinReorderCommand,\n ThreadMetaUpdateCommand,\n ThreadRuntimeModeSetCommand,\n ThreadInteractionModeSetCommand,\n ThreadTurnStartCommand,\n ThreadTurnInterruptCommand,\n ThreadApprovalRespondCommand,\n ThreadUserInputRespondCommand,\n ThreadCheckpointRevertCommand,\n ThreadSessionStopCommand,\n]);\nexport type DispatchableClientOrchestrationCommand =\n typeof DispatchableClientOrchestrationCommand.Type;\n\nexport const ClientOrchestrationCommand = Schema.Union([\n ProjectCreateCommand,\n ProjectMetaUpdateCommand,\n ProjectDeleteCommand,\n ThreadCreateCommand,\n ThreadDeleteCommand,\n ThreadArchiveCommand,\n ThreadUnarchiveCommand,\n ThreadSettleCommand,\n ThreadUnsettleCommand,\n ThreadSnoozeCommand,\n ThreadUnsnoozeCommand,\n ThreadPinCommand,\n ThreadUnpinCommand,\n ThreadPinReorderCommand,\n ThreadMetaUpdateCommand,\n ThreadRuntimeModeSetCommand,\n ThreadInteractionModeSetCommand,\n ClientThreadTurnStartCommand,\n ThreadTurnInterruptCommand,\n ThreadApprovalRespondCommand,\n ThreadUserInputRespondCommand,\n ThreadCheckpointRevertCommand,\n ThreadSessionStopCommand,\n]);\nexport type ClientOrchestrationCommand = typeof ClientOrchestrationCommand.Type;\n\nconst ThreadSessionSetCommand = Schema.Struct({\n type: Schema.Literal(\"thread.session.set\"),\n commandId: CommandId,\n threadId: ThreadId,\n session: OrchestrationSession,\n createdAt: IsoDateTime,\n});\n\nconst ThreadMessageAssistantDeltaCommand = Schema.Struct({\n type: Schema.Literal(\"thread.message.assistant.delta\"),\n commandId: CommandId,\n threadId: ThreadId,\n messageId: MessageId,\n delta: Schema.String,\n turnId: Schema.optional(TurnId),\n createdAt: IsoDateTime,\n});\n\nconst ThreadMessageAssistantCompleteCommand = Schema.Struct({\n type: Schema.Literal(\"thread.message.assistant.complete\"),\n commandId: CommandId,\n threadId: ThreadId,\n messageId: MessageId,\n turnId: Schema.optional(TurnId),\n createdAt: IsoDateTime,\n});\n\nconst ThreadProposedPlanUpsertCommand = Schema.Struct({\n type: Schema.Literal(\"thread.proposed-plan.upsert\"),\n commandId: CommandId,\n threadId: ThreadId,\n proposedPlan: OrchestrationProposedPlan,\n createdAt: IsoDateTime,\n});\n\nconst ThreadTurnDiffCompleteCommand = Schema.Struct({\n type: Schema.Literal(\"thread.turn.diff.complete\"),\n commandId: CommandId,\n threadId: ThreadId,\n turnId: TurnId,\n completedAt: IsoDateTime,\n checkpointRef: CheckpointRef,\n status: OrchestrationCheckpointStatus,\n files: Schema.Array(OrchestrationCheckpointFile),\n assistantMessageId: Schema.optional(MessageId),\n checkpointTurnCount: NonNegativeInt,\n createdAt: IsoDateTime,\n});\n\nconst ThreadActivityAppendCommand = Schema.Struct({\n type: Schema.Literal(\"thread.activity.append\"),\n commandId: CommandId,\n threadId: ThreadId,\n activity: OrchestrationThreadActivity,\n createdAt: IsoDateTime,\n});\n\nconst ThreadRevertCompleteCommand = Schema.Struct({\n type: Schema.Literal(\"thread.revert.complete\"),\n commandId: CommandId,\n threadId: ThreadId,\n turnCount: NonNegativeInt,\n createdAt: IsoDateTime,\n});\n\nconst ThreadTitleRegenerationCompleteCommand = Schema.Struct({\n type: Schema.Literal(\"thread.title.regeneration.complete\"),\n commandId: CommandId,\n threadId: ThreadId,\n requestId: CommandId,\n title: Schema.optional(TrimmedNonEmptyString),\n});\n\nconst InternalOrchestrationCommand = Schema.Union([\n ThreadSessionSetCommand,\n ThreadMessageAssistantDeltaCommand,\n ThreadMessageAssistantCompleteCommand,\n ThreadProposedPlanUpsertCommand,\n ThreadTurnDiffCompleteCommand,\n ThreadActivityAppendCommand,\n ThreadRevertCompleteCommand,\n ThreadTitleRegenerationCompleteCommand,\n]);\nexport type InternalOrchestrationCommand = typeof InternalOrchestrationCommand.Type;\n\nexport const OrchestrationCommand = Schema.Union([\n DispatchableClientOrchestrationCommand,\n InternalOrchestrationCommand,\n]);\nexport type OrchestrationCommand = typeof OrchestrationCommand.Type;", + "checksum": "318896f2aa24bd67ad6b1e40f4fd3b7ac6b7f29240f9290046af5135c8048721" + }, + "normalizer-staging-boundary": { + "id": "normalizer-staging-boundary", + "path": "apps/server/src/orchestration/Normalizer.ts", + "start": 18, + "end": 179, + "language": "typescript", + "label": "Pre-transaction timestamp, workspace, and attachment staging", + "code": "export const canonicalizeClientCommandTimestamps = (\n command: ClientOrchestrationCommand,\n receivedAt: IsoDateTime,\n): ClientOrchestrationCommand => {\n const canonicalCommand =\n \"createdAt\" in command\n ? {\n ...command,\n createdAt: receivedAt,\n }\n : command;\n\n if (canonicalCommand.type !== \"thread.turn.start\" || !canonicalCommand.bootstrap?.createThread) {\n return canonicalCommand;\n }\n\n return {\n ...canonicalCommand,\n bootstrap: {\n ...canonicalCommand.bootstrap,\n createThread: {\n ...canonicalCommand.bootstrap.createThread,\n createdAt: receivedAt,\n },\n },\n };\n};\n\nexport const normalizeDispatchCommand = (command: ClientOrchestrationCommand) =>\n Effect.gen(function* () {\n const receivedAt = DateTime.formatIso(yield* DateTime.now);\n const canonicalCommand = canonicalizeClientCommandTimestamps(command, receivedAt);\n const fileSystem = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const serverConfig = yield* ServerConfig;\n const workspacePaths = yield* WorkspacePaths.WorkspacePaths;\n\n const normalizeProjectWorkspaceRoot = (workspaceRoot: string) =>\n workspacePaths.normalizeWorkspaceRoot(workspaceRoot).pipe(\n Effect.mapError(\n (cause) =>\n new OrchestrationDispatchCommandError({\n message: cause.message,\n }),\n ),\n );\n\n const normalizeProjectWorkspaceRootForCreate = (\n workspaceRoot: string,\n createIfMissing: boolean | undefined,\n ) =>\n workspacePaths\n .normalizeWorkspaceRoot(workspaceRoot, {\n createIfMissing: createIfMissing === true,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new OrchestrationDispatchCommandError({\n message: cause.message,\n }),\n ),\n );\n\n if (canonicalCommand.type === \"project.create\") {\n return {\n ...canonicalCommand,\n workspaceRoot: yield* normalizeProjectWorkspaceRootForCreate(\n canonicalCommand.workspaceRoot,\n canonicalCommand.createWorkspaceRootIfMissing,\n ),\n createWorkspaceRootIfMissing: canonicalCommand.createWorkspaceRootIfMissing === true,\n } satisfies OrchestrationCommand;\n }\n\n if (\n canonicalCommand.type === \"project.meta.update\" &&\n canonicalCommand.workspaceRoot !== undefined\n ) {\n return {\n ...canonicalCommand,\n workspaceRoot: yield* normalizeProjectWorkspaceRoot(canonicalCommand.workspaceRoot),\n } satisfies OrchestrationCommand;\n }\n\n if (canonicalCommand.type !== \"thread.turn.start\") {\n return canonicalCommand as OrchestrationCommand;\n }\n\n const normalizedAttachments = yield* Effect.forEach(\n canonicalCommand.message.attachments,\n (attachment) =>\n Effect.gen(function* () {\n const parsed = parseBase64DataUrl(attachment.dataUrl);\n if (!parsed || !parsed.mimeType.startsWith(\"image/\")) {\n return yield* new OrchestrationDispatchCommandError({\n message: `Invalid image attachment payload for '${attachment.name}'.`,\n });\n }\n\n const bytes = Buffer.from(parsed.base64, \"base64\");\n if (bytes.byteLength === 0 || bytes.byteLength > PROVIDER_SEND_TURN_MAX_IMAGE_BYTES) {\n return yield* new OrchestrationDispatchCommandError({\n message: `Image attachment '${attachment.name}' is empty or too large.`,\n });\n }\n\n const attachmentId = createAttachmentId(canonicalCommand.threadId);\n if (!attachmentId) {\n return yield* new OrchestrationDispatchCommandError({\n message: \"Failed to create a safe attachment id.\",\n });\n }\n\n const persistedAttachment = {\n type: \"image\" as const,\n id: attachmentId,\n name: attachment.name,\n mimeType: parsed.mimeType.toLowerCase(),\n sizeBytes: bytes.byteLength,\n };\n\n const attachmentPath = resolveAttachmentPath({\n attachmentsDir: serverConfig.attachmentsDir,\n attachment: persistedAttachment,\n });\n if (!attachmentPath) {\n return yield* new OrchestrationDispatchCommandError({\n message: `Failed to resolve persisted path for '${attachment.name}'.`,\n });\n }\n\n yield* fileSystem.makeDirectory(path.dirname(attachmentPath), { recursive: true }).pipe(\n Effect.mapError(\n () =>\n new OrchestrationDispatchCommandError({\n message: `Failed to create attachment directory for '${attachment.name}'.`,\n }),\n ),\n );\n yield* fileSystem.writeFile(attachmentPath, bytes).pipe(\n Effect.mapError(\n () =>\n new OrchestrationDispatchCommandError({\n message: `Failed to persist attachment '${attachment.name}'.`,\n }),\n ),\n );\n\n return persistedAttachment;\n }),\n { concurrency: 1 },\n );\n\n return {\n ...canonicalCommand,\n message: {\n ...canonicalCommand.message,\n attachments: normalizedAttachments,\n },\n } satisfies OrchestrationCommand;\n });", + "checksum": "a6b4f3d074784de7397eed20ee1bfb7fa2de4eca5f62c5443b1962f1cdb5d6db" + }, + "turn-atomic-batch": { + "id": "turn-atomic-batch", + "path": "apps/server/src/orchestration/decider.ts", + "start": 926, + "end": 1036, + "language": "typescript", + "label": "Existing-thread turn plans a two-to-four-event batch", + "code": " case \"thread.turn.start\": {\n const targetThread = yield* requireThread({\n readModel,\n command,\n threadId: command.threadId,\n });\n const sourceProposedPlan = command.sourceProposedPlan;\n const sourceThread = sourceProposedPlan\n ? yield* requireThread({\n readModel,\n command,\n threadId: sourceProposedPlan.threadId,\n })\n : null;\n const sourcePlan =\n sourceProposedPlan && sourceThread\n ? sourceThread.proposedPlans.find((entry) => entry.id === sourceProposedPlan.planId)\n : null;\n if (sourceProposedPlan && !sourcePlan) {\n return yield* new OrchestrationCommandInvariantError({\n commandType: command.type,\n detail: `Proposed plan '${sourceProposedPlan.planId}' does not exist on thread '${sourceProposedPlan.threadId}'.`,\n });\n }\n if (sourceThread && sourceThread.projectId !== targetThread.projectId) {\n return yield* new OrchestrationCommandInvariantError({\n commandType: command.type,\n detail: `Proposed plan '${sourceProposedPlan?.planId}' belongs to thread '${sourceThread.id}' in a different project.`,\n });\n }\n const userMessageEvent: Omit = {\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.message-sent\",\n payload: {\n threadId: command.threadId,\n messageId: command.message.messageId,\n role: \"user\",\n text: command.message.text,\n attachments: command.message.attachments,\n turnId: null,\n streaming: false,\n createdAt: command.createdAt,\n updatedAt: command.createdAt,\n },\n };\n const turnStartRequestedEvent: Omit = {\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n causationEventId: userMessageEvent.eventId,\n type: \"thread.turn-start-requested\",\n payload: {\n threadId: command.threadId,\n messageId: command.message.messageId,\n ...(command.modelSelection !== undefined\n ? { modelSelection: command.modelSelection }\n : {}),\n ...(command.titleSeed !== undefined ? { titleSeed: command.titleSeed } : {}),\n runtimeMode: targetThread.runtimeMode,\n interactionMode: targetThread.interactionMode,\n ...(sourceProposedPlan !== undefined ? { sourceProposedPlan } : {}),\n createdAt: command.createdAt,\n },\n };\n // Real activity resets ANY override: it wakes an explicitly settled\n // thread, and it clears a keep-active pin back to neutral so the\n // thread can auto-settle again after this burst of work goes stale.\n // A snooze clears the same way — sending a message to a snoozed\n // thread is the user re-engaging, so the return ticket is spent.\n const lifecycleResetEvents: Array> = [];\n if (targetThread.settledOverride !== null) {\n lifecycleResetEvents.push({\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.unsettled\",\n payload: {\n threadId: command.threadId,\n reason: \"activity\",\n updatedAt: command.createdAt,\n },\n });\n }\n if (targetThread.snoozedUntil != null) {\n lifecycleResetEvents.push({\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.unsnoozed\",\n payload: {\n threadId: command.threadId,\n reason: \"activity\",\n updatedAt: command.createdAt,\n },\n });\n }\n return [...lifecycleResetEvents, userMessageEvent, turnStartRequestedEvent];", + "checksum": "0d0fe115f9ae7b07e903de3cca6dfd815044b54aa8a56b75417acb4a17410c4d" + }, + "engine-commit-publication": { + "id": "engine-commit-publication", + "path": "apps/server/src/orchestration/Layers/OrchestrationEngine.ts", + "start": 197, + "end": 259, + "language": "typescript", + "label": "SQL commit followed by in-memory fold and hot publication", + "code": " const committedCommand = yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const committedEvents: OrchestrationEvent[] = [];\n let nextCommandReadModel = commandReadModel;\n\n for (const nextEvent of eventBases) {\n const savedEvent = yield* eventStore.append(nextEvent);\n nextCommandReadModel = yield* projectEvent(nextCommandReadModel, savedEvent);\n yield* projectionPipeline.projectEvent(savedEvent);\n committedEvents.push(savedEvent);\n }\n\n const lastSavedEvent = committedEvents.at(-1) ?? null;\n if (lastSavedEvent === null) {\n return yield* new OrchestrationCommandInvariantError({\n commandType: envelope.command.type,\n detail: \"Command produced no events.\",\n });\n }\n\n yield* commandReceiptRepository.upsert({\n commandId: envelope.command.commandId,\n aggregateKind: lastSavedEvent.aggregateKind,\n aggregateId: lastSavedEvent.aggregateId,\n acceptedAt: lastSavedEvent.occurredAt,\n resultSequence: lastSavedEvent.sequence,\n status: \"accepted\",\n error: null,\n });\n\n return {\n committedEvents,\n lastSequence: lastSavedEvent.sequence,\n nextCommandReadModel,\n } as const;\n }),\n )\n .pipe(\n Effect.catchTag(\"SqlError\", (sqlError) =>\n Effect.fail(\n toPersistenceSqlError(\"OrchestrationEngine.processEnvelope:transaction\")(sqlError),\n ),\n ),\n );\n\n commandReadModel = committedCommand.nextCommandReadModel;\n for (const [index, event] of committedCommand.committedEvents.entries()) {\n yield* PubSub.publish(eventPubSub, event);\n if (index === 0) {\n yield* Metric.update(\n Metric.withAttributes(\n orchestrationCommandAckDuration,\n metricAttributes({\n ...baseMetricAttributes,\n ackEventType: event.type,\n }),\n ),\n Duration.millis(Math.max(0, (yield* Clock.currentTimeMillis) - envelope.startedAtMs)),\n );\n }\n }\n return { sequence: committedCommand.lastSequence };", + "checksum": "24e00da0c432e501172e3847817fde311d8656b07e3b8261c657ecf6b4c35d4c" + }, + "command-receipt-schema": { + "id": "command-receipt-schema", + "path": "apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts", + "start": 25, + "end": 33, + "language": "typescript", + "label": "Durable command receipt fields", + "code": "export const OrchestrationCommandReceipt = Schema.Struct({\n commandId: CommandId,\n aggregateKind: OrchestrationAggregateKind,\n aggregateId: Schema.Union([ProjectId, ThreadId]),\n acceptedAt: IsoDateTime,\n resultSequence: NonNegativeInt,\n status: OrchestrationCommandReceiptStatus,\n error: Schema.NullOr(Schema.String),\n});", + "checksum": "264f74e9b17b136921f154402d8dc87dd27cb86328043769f9293f1d8a8b451b" + }, + "projection-transaction-cursor": { + "id": "projection-transaction-cursor", + "path": "apps/server/src/orchestration/Layers/ProjectionPipeline.ts", + "start": 1609, + "end": 1678, + "language": "typescript", + "label": "Ordered projectors, transactional cursor updates, and attachment side effects", + "code": " const projectors: ReadonlyArray = [\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.projects,\n apply: applyProjectsProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.threadMessages,\n apply: applyThreadMessagesProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans,\n apply: applyThreadProposedPlansProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.threadActivities,\n apply: applyThreadActivitiesProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.threadSessions,\n apply: applyThreadSessionsProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.threadTurns,\n apply: applyThreadTurnsProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.checkpoints,\n apply: applyCheckpointsProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.pendingApprovals,\n apply: applyPendingApprovalsProjection,\n },\n {\n name: ORCHESTRATION_PROJECTOR_NAMES.threads,\n apply: applyThreadsProjection,\n },\n ];\n\n const runProjectorForEvent = Effect.fn(\"runProjectorForEvent\")(function* (\n projector: ProjectorDefinition,\n event: OrchestrationEvent,\n ) {\n const attachmentSideEffects: AttachmentSideEffects = {\n deletedThreadIds: new Set(),\n prunedThreadRelativePaths: new Map>(),\n };\n\n yield* sql.withTransaction(\n projector.apply(event, attachmentSideEffects).pipe(\n Effect.flatMap(() =>\n projectionStateRepository.upsert({\n projector: projector.name,\n lastAppliedSequence: event.sequence,\n updatedAt: event.occurredAt,\n }),\n ),\n ),\n );\n\n yield* runAttachmentSideEffects(attachmentSideEffects).pipe(\n Effect.catch((cause) =>\n Effect.logWarning(\"failed to apply projected attachment side-effects\", {\n projector: projector.name,\n sequence: event.sequence,\n eventType: event.type,\n cause,\n }),\n ),\n );", + "checksum": "ec226c4bd720884378ba5cb08e9527043641bfaac002455052b75f36ee02daa0" + }, + "snapshot-safe-watermark": { + "id": "snapshot-safe-watermark", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 195, + "end": 258, + "language": "typescript", + "label": "Snapshot watermark is the minimum required projector cursor", + "code": "const REQUIRED_SNAPSHOT_PROJECTORS = [\n ORCHESTRATION_PROJECTOR_NAMES.projects,\n ORCHESTRATION_PROJECTOR_NAMES.threads,\n ORCHESTRATION_PROJECTOR_NAMES.threadMessages,\n ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans,\n ORCHESTRATION_PROJECTOR_NAMES.threadActivities,\n ORCHESTRATION_PROJECTOR_NAMES.threadSessions,\n ORCHESTRATION_PROJECTOR_NAMES.checkpoints,\n] as const;\n\nfunction maxIso(left: string | null, right: string): string {\n if (left === null) {\n return right;\n }\n return left > right ? left : right;\n}\n\nfunction escapeLikePattern(value: string): string {\n return value.replaceAll(\"!\", \"!!\").replaceAll(\"%\", \"!%\").replaceAll(\"_\", \"!_\");\n}\n\nfunction foldAsciiCase(value: string): string {\n return value.replace(/[A-Z]/g, (character) => character.toLowerCase());\n}\n\nfunction buildSearchSnippet(text: string, query: string): string {\n const normalizedText = text.replace(/\\s+/g, \" \").trim();\n if (normalizedText.length <= 240) {\n return normalizedText;\n }\n\n const normalizedQuery = foldAsciiCase(query.replace(/\\s+/g, \" \").trim());\n const matchIndex = foldAsciiCase(normalizedText).indexOf(normalizedQuery);\n const bodyLength = 236;\n const idealStart = Math.max(0, matchIndex - 72);\n const start = Math.min(idealStart, normalizedText.length - bodyLength);\n const end = Math.min(normalizedText.length, start + bodyLength);\n return `${start > 0 ? \"…\" : \"\"}${normalizedText.slice(start, end)}${\n end < normalizedText.length ? \"…\" : \"\"\n }`;\n}\n\nfunction computeSnapshotSequence(\n stateRows: ReadonlyArray>,\n): number {\n if (stateRows.length === 0) {\n return 0;\n }\n const sequenceByProjector = new Map(\n stateRows.map((row) => [row.projector, row.lastAppliedSequence] as const),\n );\n\n let minSequence = Number.POSITIVE_INFINITY;\n for (const projector of REQUIRED_SNAPSHOT_PROJECTORS) {\n const sequence = sequenceByProjector.get(projector);\n if (sequence === undefined) {\n return 0;\n }\n if (sequence < minSequence) {\n minSequence = sequence;\n }\n }\n\n return Number.isFinite(minSequence) ? minSequence : 0;", + "checksum": "1e59d916d6fd2d68ce72a50afe86973454487d7b5b81d8215e632767ef82f3a4" + }, + "provider-reactor-forked-send": { + "id": "provider-reactor-forked-send", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1060, + "end": 1174, + "language": "typescript", + "label": "Volatile turn dedupe and forked provider send", + "code": " const processTurnStartRequested = Effect.fn(\"processTurnStartRequested\")(function* (\n event: Extract,\n ) {\n const key = turnStartKeyForEvent(event);\n if (yield* hasHandledTurnStartRecently(key)) {\n return;\n }\n\n const thread = yield* resolveThread(event.payload.threadId);\n if (!thread) {\n return;\n }\n\n const message = thread.messages.find((entry) => entry.id === event.payload.messageId);\n if (!message || message.role !== \"user\") {\n yield* appendProviderFailureActivity({\n threadId: event.payload.threadId,\n kind: \"provider.turn.start.failed\",\n summary: \"Provider turn start failed\",\n detail: `User message '${event.payload.messageId}' was not found for turn start request.`,\n turnId: null,\n createdAt: event.payload.createdAt,\n });\n return;\n }\n\n const isFirstUserMessageTurn =\n thread.messages.filter((entry) => entry.role === \"user\").length === 1;\n if (isFirstUserMessageTurn) {\n const project = yield* resolveProject(thread.projectId);\n const generationCwd =\n resolveThreadWorkspaceCwd({\n thread,\n projects: project ? [project] : [],\n }) ?? process.cwd();\n const generationInput = {\n messageText: message.text,\n ...(message.attachments !== undefined ? { attachments: message.attachments } : {}),\n ...(event.payload.titleSeed !== undefined ? { titleSeed: event.payload.titleSeed } : {}),\n };\n\n yield* maybeGenerateAndRenameWorktreeBranchForFirstTurn({\n threadId: event.payload.threadId,\n branch: thread.branch,\n worktreePath: thread.worktreePath,\n ...generationInput,\n }).pipe(Effect.forkScoped);\n\n if (canReplaceThreadTitle(thread.title, event.payload.titleSeed)) {\n yield* maybeGenerateThreadTitleForFirstTurn({\n threadId: event.payload.threadId,\n cwd: generationCwd,\n ...generationInput,\n }).pipe(Effect.forkScoped);\n }\n }\n\n const handleTurnStartFailure = (cause: Cause.Cause) => {\n if (Cause.hasInterruptsOnly(cause)) {\n return Effect.void;\n }\n const detail = formatFailureDetail(cause);\n return setThreadSessionErrorOnTurnStartFailure({\n threadId: event.payload.threadId,\n detail,\n createdAt: event.payload.createdAt,\n }).pipe(\n Effect.flatMap(() =>\n appendProviderFailureActivity({\n threadId: event.payload.threadId,\n kind: \"provider.turn.start.failed\",\n summary: \"Provider turn start failed\",\n detail,\n turnId: null,\n createdAt: event.payload.createdAt,\n }),\n ),\n Effect.asVoid,\n );\n };\n\n const recoverTurnStartFailure = (cause: Cause.Cause) =>\n handleTurnStartFailure(cause).pipe(\n Effect.catchCause((recoveryCause) =>\n Effect.logWarning(\"provider command reactor failed to recover turn start failure\", {\n eventType: event.type,\n threadId: event.payload.threadId,\n cause: Cause.pretty(recoveryCause),\n originalCause: Cause.pretty(cause),\n }),\n ),\n );\n\n const sendTurnRequest = yield* buildSendTurnRequestForThread({\n threadId: event.payload.threadId,\n messageText: message.text,\n ...(message.attachments !== undefined ? { attachments: message.attachments } : {}),\n ...(event.payload.modelSelection !== undefined\n ? { modelSelection: event.payload.modelSelection }\n : {}),\n interactionMode: event.payload.interactionMode,\n createdAt: event.payload.createdAt,\n }).pipe(\n Effect.map(Option.some),\n Effect.catchCause((cause) => handleTurnStartFailure(cause).pipe(Effect.as(Option.none()))),\n );\n\n if (Option.isNone(sendTurnRequest)) {\n return;\n }\n\n yield* providerService\n .sendTurn(sendTurnRequest.value)\n .pipe(Effect.catchCause(recoverTurnStartFailure), Effect.forkScoped);\n });", + "checksum": "e612e2a0295ab2afbf9d9b7a9d4c7da0578c4adf5b052b24892d929ec9995f00" + }, + "sqlite-runtime-pragmas": { + "id": "sqlite-runtime-pragmas", + "path": "apps/server/src/persistence/Layers/Sqlite.ts", + "start": 24, + "end": 66, + "language": "typescript", + "label": "SQLite runtime selection, pragmas, migrations, and scoped layers", + "code": "const makeRuntimeSqliteLayer = Effect.fn(\"makeRuntimeSqliteLayer\")(function* (\n config: RuntimeSqliteLayerConfig,\n) {\n const runtime = process.versions.bun !== undefined ? \"bun\" : \"node\";\n const loader = defaultSqliteClientLoaders[runtime];\n const clientModule = yield* Effect.promise(loader);\n return clientModule.layer(config);\n}, Layer.unwrap);\n\nconst setup = Layer.effectDiscard(\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n // CLI and server write from separate processes; wait rather than fail with SQLITE_BUSY.\n yield* sql`PRAGMA busy_timeout = 5000;`;\n yield* sql`PRAGMA foreign_keys = ON;`;\n yield* sql`PRAGMA journal_mode = WAL;`;\n yield* runMigrations();\n }),\n);\n\nexport const makeSqlitePersistenceLive = Effect.fn(\"makeSqlitePersistenceLive\")(function* (\n dbPath: string,\n) {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n yield* fs.makeDirectory(path.dirname(dbPath), { recursive: true });\n\n return Layer.provideMerge(\n setup,\n makeRuntimeSqliteLayer({\n filename: dbPath,\n spanAttributes: {\n \"db.name\": path.basename(dbPath),\n \"service.name\": \"t3-server\",\n },\n }),\n );\n}, Layer.unwrap);\n\nexport const SqlitePersistenceMemory = Layer.provideMerge(\n setup,\n makeRuntimeSqliteLayer({ filename: \":memory:\" }),\n);", + "checksum": "82fedbba97c179c80bcbcc9e8ae8dc674681b57716267f1b03717e76fcaa5ee3" + }, + "provider-instance-identity-contract": { + "id": "provider-instance-identity-contract", + "path": "packages/contracts/src/providerInstance.ts", + "start": 4, + "end": 32, + "language": "typescript", + "label": "Driver kind and configured instance identity", + "code": " * Splits the historical \"provider kind\" concept into two:\n *\n * - `ProviderDriverKind` is the implementation kind selector (e.g. codex,\n * claudeAgent, a fork's `ollama`, …). It picks which driver package\n * handles the protocol, the probe, the adapter, and text generation.\n *\n * - `ProviderInstanceId` is the routing key (a user-defined slug).\n * Threads, sessions, runtime events, and persisted bindings reference\n * instance ids — never driver kinds — so a user can configure multiple\n * instances of the same driver (e.g. `codex_personal` + `codex_work`),\n * each with independent driver-specific configuration.\n *\n * Forward/backward compatibility invariant\n * ----------------------------------------\n * `ProviderDriverKind` is intentionally an **open** branded slug, not a closed\n * literal union. The server hosts forks, ships in PRs that add drivers, and\n * users frequently roll between branches and forks. Any of those paths can\n * leave `ServerSettings`, persisted thread state, or session bindings\n * referencing a driver that the currently-running build does not know about.\n *\n * The rule: parsing any of those payloads must always succeed, and the\n * runtime is responsible for marking the unknown driver/instance as\n * \"unavailable\" rather than crashing. Built-in drivers shipped by the core\n * product happens to register in a given build is not part of the contract\n * layer. Driver availability is discovered through the runtime registry.\n *\n * Driver-specific configuration is similarly opaque at the contracts layer:\n * drivers live in (or will be extracted to) their own packages and own their\n * config schemas. The contracts package only knows the envelope.", + "checksum": "c407854da6ce483f2fa76dd285ed7e16f5708176e172140e34c28cc8248e9176" + }, + "provider-driver-instance-spi": { + "id": "provider-driver-instance-spi", + "path": "apps/server/src/provider/ProviderDriver.ts", + "start": 55, + "end": 117, + "language": "typescript", + "label": "Scoped provider driver and instance records", + "code": "/**\n * One materialized provider instance. Held by the registry, looked up by\n * `instanceId`, torn down by closing the scope it was created in.\n *\n * The three \"shape\" fields are captured closures owned by this instance —\n * stopping one instance cannot affect another, and starting a second\n * instance of the same driver does not reach into the first instance's\n * state.\n */\nexport interface ProviderInstance {\n readonly instanceId: ProviderInstanceId;\n readonly driverKind: ProviderDriverKind;\n readonly continuationIdentity: ProviderContinuationIdentity;\n readonly displayName: string | undefined;\n readonly accentColor?: string | undefined;\n readonly enabled: boolean;\n readonly snapshot: ServerProviderShape;\n readonly adapter: ProviderAdapterShape;\n readonly textGeneration: TextGeneration.TextGeneration[\"Service\"];\n}\n\nexport interface ProviderContinuationIdentity {\n readonly driverKind: ProviderDriverKind;\n readonly continuationKey: string;\n}\n\nexport function defaultProviderContinuationIdentity(input: {\n readonly driverKind: ProviderDriverKind;\n readonly instanceId: ProviderInstanceId;\n}): ProviderContinuationIdentity {\n return {\n driverKind: input.driverKind,\n continuationKey: `${input.driverKind}:instance:${input.instanceId}`,\n };\n}\n\n/**\n * Inputs the registry passes to a driver's `create` function.\n *\n * `config` is the typed payload — already decoded by the registry through\n * `driver.configSchema`. Drivers never decode their own raw envelope.\n */\nexport interface ProviderDriverCreateInput {\n readonly instanceId: ProviderInstanceId;\n readonly displayName: string | undefined;\n readonly accentColor?: string | undefined;\n readonly environment: ProviderInstanceEnvironment;\n readonly enabled: boolean;\n readonly config: Config;\n}\n\n/**\n * Driver SPI — registered as a plain value, not a Layer.\n *\n * `Config` is whatever the driver decoded from\n * `ProviderInstanceConfig.config`. `R` is the union of infrastructure\n * services the driver depends on; the registry layer aggregates `R` across\n * all registered drivers and the runtime supplies them.\n *\n * `create` is responsible for *all* per-instance state — process handles,\n * pubsub topics, refs, file watchers — and must release them when its\n * scope closes. Two calls to `create` with different `instanceId` /\n * `config` MUST yield instances with no shared mutable state.", + "checksum": "d6fe18a1ab845da33fc05cb2ef822ef1057706345468a8b485daa76abaa9fce6" + }, + "provider-driver-instance-records": { + "id": "provider-driver-instance-records", + "path": "apps/server/src/provider/ProviderDriver.ts", + "start": 4, + "end": 20, + "language": "typescript", + "label": "Plain provider driver and instance record contracts", + "code": " * `ProviderDriver` is a record, not a Context.Service. The thing it produces\n * (`ProviderInstance`) is also a record — three captured closures\n * (`snapshot`, `adapter`, `textGeneration`), an id, and a driver kind. There\n * are intentionally no per-driver Context tags because tags are\n * singleton-per-runtime and we need many instances of the same driver.\n *\n * The only Effect service involved is `ProviderInstanceRegistry`, which\n * owns the live `Map` and is itself a\n * singleton.\n *\n * Driver factories are functions of `(typed config, env)` where:\n * - `typed config` is decoded once by the registry via `configSchema`,\n * so drivers never deal with raw `unknown`.\n * - `env` flows through Effect's R channel. Each driver declares the\n * subset of infrastructure services it needs (FileSystem,\n * ChildProcessSpawner, …) on its `create` return type; the registry\n * layer's R is the union of those, and the runtime layer satisfies it.", + "checksum": "930d8e1e57ebe1e79b5e332f52c8b90908310361e4c752ca17ed828f405b7d22" + }, + "codex-app-server-client-typed-stdio": { + "id": "codex-app-server-client-typed-stdio", + "path": "packages/effect-codex-app-server/src/client.ts", + "start": 140, + "end": 211, + "language": "typescript", + "label": "Typed Codex notifications, requests, and transport calls", + "code": " const dispatchNotification = (\n notification: CodexProtocol.CodexAppServerIncomingNotification,\n ): Effect.Effect => {\n const schema =\n notification.method in CodexRpc.SERVER_NOTIFICATION_PARAMS\n ? CodexRpc.SERVER_NOTIFICATION_PARAMS[\n notification.method as CodexRpc.ServerNotificationMethod\n ]\n : undefined;\n const handlers = notificationHandlers.get(notification.method) ?? [];\n\n if (schema) {\n return decodeNotificationPayload(notification.method, schema, notification.params).pipe(\n Effect.flatMap((decoded) =>\n Effect.forEach(handlers, (handler) => handler(decoded), { discard: true }),\n ),\n Effect.catch(() => Effect.void),\n );\n }\n\n return unknownNotificationHandler\n ? unknownNotificationHandler(notification.method, notification.params).pipe(\n Effect.catch(() => Effect.void),\n )\n : Effect.void;\n };\n\n const dispatchRequest = (\n request: CodexProtocol.CodexAppServerIncomingRequest,\n ): Effect.Effect => {\n if (request.method in CodexRpc.SERVER_REQUEST_PARAMS) {\n const method = request.method as CodexRpc.ServerRequestMethod;\n const payloadSchema = getServerRequestParamSchema(method);\n const responseSchema = getServerRequestResponseSchema(method);\n const handler = requestHandlers.get(method);\n\n return decodeOptionalPayload(method, payloadSchema, request.params).pipe(\n Effect.flatMap((decoded) => runHandler(handler, decoded, method)),\n Effect.flatMap((result) => encodeOptionalPayload(method, responseSchema, result)),\n );\n }\n\n return unknownRequestHandler\n ? unknownRequestHandler(request.method, request.params)\n : Effect.fail(CodexError.CodexAppServerRequestError.methodNotFound(request.method));\n };\n\n const transport = yield* CodexProtocol.makeCodexAppServerPatchedProtocol({\n stdio,\n ...(terminationError ? { terminationError } : {}),\n ...(options.logIncoming !== undefined ? { logIncoming: options.logIncoming } : {}),\n ...(options.logOutgoing !== undefined ? { logOutgoing: options.logOutgoing } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n onNotification: dispatchNotification,\n onRequest: dispatchRequest,\n });\n\n const request = (\n method: M,\n payload: CodexRpc.ClientRequestParamsByMethod[M],\n ): Effect.Effect =>\n encodeOptionalPayload(method, getClientRequestParamSchema(method), payload).pipe(\n Effect.flatMap((encoded) => transport.request(method, encoded)),\n Effect.flatMap(\n (\n raw,\n ): Effect.Effect<\n CodexRpc.ClientRequestResponsesByMethod[M],\n CodexError.CodexAppServerError\n > => decodeOptionalPayload(method, getClientRequestResponseSchema(method), raw),\n ),\n );", + "checksum": "296b35c49fcafff9f8d6d65ab7403039c19f08f7c8e6f0a9350e22dfc01a1cf1" + }, + "codex-adapter-session-runtime": { + "id": "codex-adapter-session-runtime", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1642, + "end": 1693, + "language": "typescript", + "label": "Codex session replacement and runtime configuration", + "code": " const startSession: CodexAdapterShape[\"startSession\"] = (input) =>\n Effect.scoped(\n Effect.gen(function* () {\n if (input.provider !== undefined && input.provider !== PROVIDER) {\n return yield* new ProviderAdapterValidationError({\n provider: PROVIDER,\n operation: \"startSession\",\n issue: `Expected provider '${PROVIDER}' but received '${input.provider}'.`,\n });\n }\n\n const existing = sessions.get(input.threadId);\n if (existing && !existing.stopped) {\n yield* Effect.suspend(() => stopSessionInternal(existing));\n }\n\n const serviceTier =\n input.modelSelection?.instanceId === boundInstanceId\n ? getCodexServiceTierOptionValue(input.modelSelection)\n : undefined;\n const mcpSession = McpProviderSession.readMcpProviderSession(input.threadId);\n const runtimeInput: CodexSessionRuntimeOptions = {\n threadId: input.threadId,\n providerInstanceId: boundInstanceId,\n cwd: input.cwd ?? process.cwd(),\n binaryPath: codexConfig.binaryPath,\n launchArgs: resolveCodexLaunchArgs(codexConfig.launchArgs, options?.environment),\n ...(options?.environment ? { environment: options.environment } : {}),\n ...(codexConfig.homePath ? { homePath: codexConfig.homePath } : {}),\n ...(isCodexResumeCursorSchema(input.resumeCursor)\n ? { resumeCursor: input.resumeCursor }\n : {}),\n runtimeMode: input.runtimeMode,\n ...(input.modelSelection?.instanceId === boundInstanceId\n ? { model: input.modelSelection.model }\n : {}),\n ...(serviceTier ? { serviceTier } : {}),\n ...(mcpSession\n ? {\n environment: {\n ...(options?.environment ?? process.env),\n T3_MCP_BEARER_TOKEN: mcpSession.authorizationHeader.replace(/^Bearer\\s+/, \"\"),\n },\n appServerArgs: [\n \"-c\",\n `mcp_servers.t3-code.url=${mcpSession.endpoint}`,\n \"-c\",\n 'mcp_servers.t3-code.bearer_token_env_var=\"T3_MCP_BEARER_TOKEN\"',\n ],\n }\n : {}),\n };", + "checksum": "6dd08ac4e760401826162f8d3a0d739b58ed890361c817cb7b726329818dee33" + }, + "codex-adapter-runtime-events": { + "id": "codex-adapter-runtime-events", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1000, + "end": 1084, + "language": "typescript", + "label": "Codex usage, turn, and plan event normalization", + "code": " if (event.method === \"thread/tokenUsage/updated\") {\n const payload = readPayload(\n EffectCodexSchema.V2ThreadTokenUsageUpdatedNotification,\n event.payload,\n );\n const normalizedUsage = payload ? normalizeCodexTokenUsage(payload.tokenUsage) : undefined;\n if (!normalizedUsage) {\n return [];\n }\n return [\n {\n type: \"thread.token-usage.updated\",\n ...runtimeEventBase(event, canonicalThreadId),\n payload: {\n usage: normalizedUsage,\n },\n },\n ];\n }\n\n if (event.method === \"turn/started\") {\n const turnId = event.turnId;\n if (!turnId) {\n return [];\n }\n return [\n {\n ...runtimeEventBase(event, canonicalThreadId),\n turnId,\n type: \"turn.started\",\n payload: {},\n },\n ];\n }\n\n if (event.method === \"turn/completed\") {\n const payload = readPayload(EffectCodexSchema.V2TurnCompletedNotification, event.payload);\n if (!payload) {\n return [];\n }\n const errorMessage = trimText(payload.turn.error?.message);\n return [\n {\n ...runtimeEventBase(event, canonicalThreadId),\n type: \"turn.completed\",\n payload: {\n state: toTurnStatus(payload.turn.status),\n ...(errorMessage ? { errorMessage } : {}),\n },\n },\n ];\n }\n\n if (event.method === \"turn/aborted\") {\n return [\n {\n ...runtimeEventBase(event, canonicalThreadId),\n type: \"turn.aborted\",\n payload: {\n reason: event.message ?? \"Turn aborted\",\n },\n },\n ];\n }\n\n if (event.method === \"turn/plan/updated\") {\n const payload = readPayload(EffectCodexSchema.V2TurnPlanUpdatedNotification, event.payload);\n if (!payload) {\n return [];\n }\n return [\n {\n ...runtimeEventBase(event, canonicalThreadId),\n type: \"turn.plan.updated\",\n payload: {\n ...(trimText(payload.explanation) ? { explanation: trimText(payload.explanation) } : {}),\n plan: payload.plan.map((step) => ({\n step: trimText(step.step) ?? \"step\",\n status:\n step.status === \"completed\" || step.status === \"inProgress\" ? step.status : \"pending\",\n })),\n },\n },\n ];\n }", + "checksum": "4b82fdd81df8d8a061c9f7f0b036c32d5f5bf061f9511189548f386a038f4d9f" + }, + "claude-adapter-query-config": { + "id": "claude-adapter-query-config", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4138, + "end": 4196, + "language": "typescript", + "label": "Claude permission mapping and query option assembly", + "code": " const runtimeModeToPermission: Record = {\n \"auto-accept-edits\": \"acceptEdits\",\n auto: \"auto\",\n \"full-access\": \"bypassPermissions\",\n };\n const permissionMode = runtimeModeToPermission[input.runtimeMode];\n const settings = {\n ...(typeof thinking === \"boolean\" ? { alwaysThinkingEnabled: thinking } : {}),\n ...(fastMode ? { fastMode: true } : {}),\n ...(ultracode ? { ultracode: true } : {}),\n };\n const mcpSession = McpProviderSession.readMcpProviderSession(input.threadId);\n // The attachments dir grant lets the agent Read/copy pasted images at\n // the paths ProviderService injects into the turn text, without an\n // approval prompt. It is a leaf directory holding only attachment\n // files; siblings like secrets/ and state.sqlite stay ungranted.\n const additionalDirectories = [\n ...(input.cwd ? [input.cwd] : []),\n serverConfig.attachmentsDir,\n ];\n const queryOptions: ClaudeQueryOptions = {\n ...(input.cwd ? { cwd: input.cwd } : {}),\n ...(apiModelId ? { model: apiModelId } : {}),\n pathToClaudeCodeExecutable: claudeBinaryPath,\n systemPrompt: { type: \"preset\", preset: \"claude_code\" },\n settingSources: [...CLAUDE_SETTING_SOURCES],\n // `ultracode` is a Claude Code setting, not an API effort level. It is\n // normalized to `xhigh` above and paired with `settings.ultracode`.\n ...(effectiveEffort\n ? {\n effort: effectiveEffort as unknown as NonNullable,\n }\n : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(permissionMode === \"bypassPermissions\"\n ? { allowDangerouslySkipPermissions: true }\n : {}),\n ...(Object.keys(settings).length > 0 ? { settings } : {}),\n ...(existingResumeSessionId ? { resume: existingResumeSessionId } : {}),\n ...(newSessionId ? { sessionId: newSessionId } : {}),\n includePartialMessages: true,\n canUseTool,\n env: claudeEnvironment,\n additionalDirectories,\n ...(Object.keys(extraArgs).length > 0 ? { extraArgs } : {}),\n ...(mcpSession\n ? {\n mcpServers: {\n \"t3-code\": {\n type: \"http\",\n url: mcpSession.endpoint,\n headers: {\n Authorization: mcpSession.authorizationHeader,\n },\n },\n },\n }\n : {}),\n };", + "checksum": "0b8c0d482fc624fb131e748d735394497afa9d437867ad9c1bee9f2f2119de08" + }, + "claude-query-invocation": { + "id": "claude-query-invocation", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4223, + "end": 4235, + "language": "typescript", + "label": "Claude SDK query invocation", + "code": " const queryRuntime = yield* Effect.try({\n try: () =>\n createQuery({\n prompt,\n options: queryOptions,\n }),\n catch: (cause) =>\n new ProviderAdapterProcessError({\n provider: PROVIDER,\n threadId,\n detail: \"Failed to start Claude runtime session.\",\n cause,\n }),", + "checksum": "293fa0c20180cf51eb8c621ce2d48809cb91db55d182270896f857d245b8a7a1" + }, + "claude-adapter-interaction-handlers": { + "id": "claude-adapter-interaction-handlers", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 4497, + "end": 4529, + "language": "typescript", + "label": "Claude approval and structured-input deferreds", + "code": " const respondToRequest: ClaudeAdapterShape[\"respondToRequest\"] = Effect.fn(\"respondToRequest\")(\n function* (threadId, requestId, decision) {\n const context = yield* requireSession(threadId);\n const pending = context.pendingApprovals.get(requestId);\n if (!pending) {\n return yield* new ProviderAdapterRequestError({\n provider: PROVIDER,\n method: \"item/requestApproval/decision\",\n detail: `Unknown pending approval request: ${requestId}`,\n });\n }\n\n context.pendingApprovals.delete(requestId);\n yield* Deferred.succeed(pending.decision, decision);\n },\n );\n\n const respondToUserInput: ClaudeAdapterShape[\"respondToUserInput\"] = Effect.fn(\n \"respondToUserInput\",\n )(function* (threadId, requestId, answers) {\n const context = yield* requireSession(threadId);\n const pending = context.pendingUserInputs.get(requestId);\n if (!pending) {\n return yield* new ProviderAdapterRequestError({\n provider: PROVIDER,\n method: \"item/tool/respondToUserInput\",\n detail: `Unknown pending user-input request: ${requestId}`,\n });\n }\n\n context.pendingUserInputs.delete(requestId);\n yield* Deferred.succeed(pending.answers, answers);\n });", + "checksum": "e41de225714771b18fce1f2bcaff53bc79bfff542df321078c5ab4d1ff8086d2" + }, + "acp-client-typed-surface": { + "id": "acp-client-typed-surface", + "path": "packages/effect-acp/src/client.ts", + "start": 40, + "end": 134, + "language": "typescript", + "label": "Typed ACP session command surface", + "code": " {\n readonly raw: AcpClientRaw;\n readonly agent: {\n /**\n * Initializes the ACP session and negotiates capabilities.\n * @see https://agentclientprotocol.com/protocol/schema#initialize\n */\n readonly initialize: (\n payload: AcpSchema.InitializeRequest,\n ) => Effect.Effect;\n /**\n * Performs ACP authentication when the agent requires it.\n * @see https://agentclientprotocol.com/protocol/schema#authenticate\n */\n readonly authenticate: (\n payload: AcpSchema.AuthenticateRequest,\n ) => Effect.Effect;\n /**\n * Logs out the current ACP identity.\n * @see https://agentclientprotocol.com/protocol/schema#logout\n */\n readonly logout: (\n payload: AcpSchema.LogoutRequest,\n ) => Effect.Effect;\n /**\n * Starts a new ACP session.\n * @see https://agentclientprotocol.com/protocol/schema#session/new\n */\n readonly createSession: (\n payload: AcpSchema.NewSessionRequest,\n ) => Effect.Effect;\n /**\n * Loads a previously saved ACP session.\n * @see https://agentclientprotocol.com/protocol/schema#session/load\n */\n readonly loadSession: (\n payload: AcpSchema.LoadSessionRequest,\n ) => Effect.Effect;\n /**\n * Lists available ACP sessions.\n * @see https://agentclientprotocol.com/protocol/schema#session/list\n */\n readonly listSessions: (\n payload: AcpSchema.ListSessionsRequest,\n ) => Effect.Effect;\n /**\n * Forks an ACP session.\n * @see https://agentclientprotocol.com/protocol/schema#session/fork\n */\n readonly forkSession: (\n payload: AcpSchema.ForkSessionRequest,\n ) => Effect.Effect;\n /**\n * Resumes an ACP session.\n * @see https://agentclientprotocol.com/protocol/schema#session/resume\n */\n readonly resumeSession: (\n payload: AcpSchema.ResumeSessionRequest,\n ) => Effect.Effect;\n /**\n * Closes an ACP session.\n * @see https://agentclientprotocol.com/protocol/schema#session/close\n */\n readonly closeSession: (\n payload: AcpSchema.CloseSessionRequest,\n ) => Effect.Effect;\n /**\n * Selects the active model for a session.\n * @see https://agentclientprotocol.com/protocol/schema#session/set_model\n */\n readonly setSessionModel: (\n payload: AcpSchema.SetSessionModelRequest,\n ) => Effect.Effect;\n /**\n * Updates a session configuration option.\n * @see https://agentclientprotocol.com/protocol/schema#session/set_config_option\n */\n readonly setSessionConfigOption: (\n payload: AcpSchema.SetSessionConfigOptionRequest,\n ) => Effect.Effect;\n /**\n * Sends a prompt turn to the agent.\n * @see https://agentclientprotocol.com/protocol/schema#session/prompt\n */\n readonly prompt: (\n payload: AcpSchema.PromptRequest,\n ) => Effect.Effect;\n /**\n * Sends a real ACP `session/cancel` notification.\n * @see https://agentclientprotocol.com/protocol/schema#session/cancel\n */\n readonly cancel: (\n payload: AcpSchema.CancelNotification,\n ) => Effect.Effect;\n };", + "checksum": "7df29bfbf9bbea09d570a845e6123253b3cee19ee9af1f4837fbf6d050040856" + }, + "cursor-session-mode-selection": { + "id": "cursor-session-mode-selection", + "path": "apps/server/src/provider/Layers/CursorAdapter.ts", + "start": 217, + "end": 294, + "language": "typescript", + "label": "Cursor negotiated mode and model selection", + "code": "function resolveRequestedModeId(input: {\n readonly interactionMode: ProviderInteractionMode | undefined;\n readonly runtimeMode: RuntimeMode;\n readonly modeState: AcpSessionModeState | undefined;\n}): string | undefined {\n const modeState = input.modeState;\n if (!modeState) {\n return undefined;\n }\n\n if (input.interactionMode === \"plan\") {\n return findModeByAliases(modeState.availableModes, ACP_PLAN_MODE_ALIASES)?.id;\n }\n\n if (input.runtimeMode === \"approval-required\") {\n return (\n findModeByAliases(modeState.availableModes, ACP_APPROVAL_MODE_ALIASES)?.id ??\n findModeByAliases(modeState.availableModes, ACP_IMPLEMENT_MODE_ALIASES)?.id ??\n modeState.availableModes.find((mode) => !isPlanMode(mode))?.id ??\n modeState.currentModeId\n );\n }\n\n return (\n findModeByAliases(modeState.availableModes, ACP_IMPLEMENT_MODE_ALIASES)?.id ??\n findModeByAliases(modeState.availableModes, ACP_APPROVAL_MODE_ALIASES)?.id ??\n modeState.availableModes.find((mode) => !isPlanMode(mode))?.id ??\n modeState.currentModeId\n );\n}\n\nfunction applyRequestedSessionConfiguration(input: {\n readonly runtime: AcpSessionRuntime.AcpSessionRuntime[\"Service\"];\n readonly runtimeMode: RuntimeMode;\n readonly interactionMode: ProviderInteractionMode | undefined;\n readonly modelSelection:\n | {\n readonly model: string;\n readonly options?: ReadonlyArray | null | undefined;\n }\n | undefined;\n readonly mapError: (context: {\n readonly cause: import(\"effect-acp/errors\").AcpError;\n readonly method: \"session/set_config_option\" | \"session/set_mode\";\n }) => E;\n}): Effect.Effect {\n return Effect.gen(function* () {\n if (input.modelSelection) {\n yield* applyCursorAcpModelSelection({\n runtime: input.runtime,\n model: input.modelSelection.model,\n selections: input.modelSelection.options,\n mapError: ({ cause }) =>\n input.mapError({\n cause,\n method: \"session/set_config_option\",\n }),\n });\n }\n\n const requestedModeId = resolveRequestedModeId({\n interactionMode: input.interactionMode,\n runtimeMode: input.runtimeMode,\n modeState: yield* input.runtime.getModeState,\n });\n if (!requestedModeId) {\n return;\n }\n\n yield* input.runtime.setMode(requestedModeId).pipe(\n Effect.mapError((cause) =>\n input.mapError({\n cause,\n method: \"session/set_mode\",\n }),\n ),\n );\n });", + "checksum": "496d6f291b2b479eb2836b32aeafe501dcc9f66a5d207cb94adf592c9f4a6a78" + }, + "grok-acp-runtime-support": { + "id": "grok-acp-runtime-support", + "path": "apps/server/src/provider/acp/GrokAcpSupport.ts", + "start": 31, + "end": 108, + "language": "typescript", + "label": "Grok ACP launch, authentication, and model selection", + "code": "\nexport function buildGrokAcpSpawnInput(\n grokSettings: GrokAcpRuntimeGrokSettings | null | undefined,\n cwd: string,\n environment?: NodeJS.ProcessEnv,\n): AcpSessionRuntime.AcpSpawnInput {\n return {\n command: grokSettings?.binaryPath || \"grok\",\n args: [\"agent\", \"stdio\"],\n cwd,\n env: {\n ...environment,\n [GROK_OAUTH2_REFERRER_ENV]: T3_CODE_OAUTH_REFERRER,\n },\n };\n}\n\nfunction resolveGrokAuthMethodId(environment: NodeJS.ProcessEnv | undefined): string {\n return environment?.[GROK_API_KEY_ENV]?.trim()\n ? GROK_AUTH_METHOD_API_KEY\n : GROK_AUTH_METHOD_CACHED_TOKEN;\n}\n\nexport const makeGrokAcpRuntime = (\n input: GrokAcpRuntimeInput,\n): Effect.Effect<\n AcpSessionRuntime.AcpSessionRuntime[\"Service\"],\n EffectAcpErrors.AcpError,\n Crypto.Crypto | Scope.Scope\n> =>\n Effect.gen(function* () {\n const acpContext = yield* Layer.build(\n AcpSessionRuntime.layer({\n ...input,\n spawn: buildGrokAcpSpawnInput(input.grokSettings, input.cwd, input.environment),\n authMethodId: resolveGrokAuthMethodId(input.environment),\n }).pipe(\n Layer.provide(\n Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, input.childProcessSpawner),\n ),\n ),\n );\n const runtime = yield* Effect.service(AcpSessionRuntime.AcpSessionRuntime).pipe(\n Effect.provide(acpContext),\n );\n return yield* makeXAiPromptCompletionRuntime(runtime);\n });\n\nexport function resolveGrokAcpBaseModelId(model: string | null | undefined): string {\n const trimmed = model?.trim();\n const base = trimmed && trimmed.length > 0 ? trimmed : \"grok-build\";\n return normalizeModelSlug(base, GROK_DRIVER_KIND) ?? \"grok-build\";\n}\n\nexport function currentGrokModelIdFromSessionSetup(\n sessionSetupResult:\n | EffectAcpSchema.LoadSessionResponse\n | EffectAcpSchema.NewSessionResponse\n | EffectAcpSchema.ResumeSessionResponse,\n): string | undefined {\n return sessionSetupResult.models?.currentModelId?.trim() || undefined;\n}\n\nexport function applyGrokAcpModelSelection(input: {\n readonly runtime: Pick;\n readonly currentModelId: string | undefined;\n readonly requestedModelId: string | undefined;\n readonly mapError: (cause: EffectAcpErrors.AcpError) => E;\n}): Effect.Effect {\n const shouldSwitchModel =\n input.requestedModelId !== undefined && input.requestedModelId !== input.currentModelId;\n if (!shouldSwitchModel) {\n return Effect.succeed(input.currentModelId);\n }\n return input.runtime\n .setSessionModel(input.requestedModelId)\n .pipe(Effect.mapError(input.mapError), Effect.as(input.requestedModelId));\n}", + "checksum": "d76d1518eb9e2c11e37e359f1d1324099034f92d77f9e6f5af7a3d167bcd168a" + }, + "opencode-runtime-ownership": { + "id": "opencode-runtime-ownership", + "path": "apps/server/src/provider/opencodeRuntime.ts", + "start": 140, + "end": 177, + "language": "typescript", + "label": "Local and external OpenCode server ownership", + "code": "export interface OpenCodeRuntimeShape {\n /**\n * Spawns a local OpenCode server process. Its lifetime is bound to the caller's\n * `Scope.Scope` — the child is killed automatically when that scope closes.\n * Consumers that want a long-lived server must create and hold a scope explicitly\n * (see {@link Scope.make}) and close it when done.\n */\n readonly startOpenCodeServerProcess: (input: {\n readonly binaryPath: string;\n readonly environment?: NodeJS.ProcessEnv;\n readonly port?: number;\n readonly hostname?: string;\n readonly timeoutMs?: number;\n }) => Effect.Effect;\n /**\n * Returns a handle to either an externally-managed OpenCode server (when\n * `serverUrl` is provided — no lifetime is attached to the caller's scope) or a\n * freshly spawned local server whose lifetime is bound to the caller's scope.\n */\n readonly connectToOpenCodeServer: (input: {\n readonly binaryPath: string;\n readonly serverUrl?: string | null;\n readonly environment?: NodeJS.ProcessEnv;\n readonly port?: number;\n readonly hostname?: string;\n readonly timeoutMs?: number;\n }) => Effect.Effect;\n readonly runOpenCodeCommand: (input: {\n readonly binaryPath: string;\n readonly args: ReadonlyArray;\n readonly environment?: NodeJS.ProcessEnv;\n readonly cwd?: string;\n }) => Effect.Effect;\n readonly createOpenCodeSdkClient: (input: {\n readonly baseUrl: string;\n readonly directory: string;\n readonly serverPassword?: string;\n }) => OpencodeClient;", + "checksum": "846dada188ac95cfa4616580a5fa9aacefea446eb2542ea69ed44236f20b6dea" + }, + "opencode-turn-and-revert": { + "id": "opencode-turn-and-revert", + "path": "apps/server/src/provider/Layers/OpenCodeAdapter.ts", + "start": 1430, + "end": 1509, + "language": "typescript", + "label": "OpenCode prompt and steering path", + "code": " const sendTurn: OpenCodeAdapterShape[\"sendTurn\"] = Effect.fn(\"sendTurn\")(function* (input) {\n const context = yield* ensureSessionContext(sessions, input.threadId);\n // A sendTurn while a turn is active is a steer: OpenCode queues the\n // prompt into the busy session and the work continues as one turn, so\n // the active turn id is reused instead of opening a new turn.\n const steeringTurnId = context.activeTurnId;\n const turnId = steeringTurnId ?? TurnId.make(`opencode-turn-${yield* randomUUIDv4}`);\n const modelSelection =\n input.modelSelection ??\n (context.session.model\n ? { instanceId: boundInstanceId, model: context.session.model }\n : undefined);\n if (modelSelection !== undefined && modelSelection.instanceId !== boundInstanceId) {\n return yield* new ProviderAdapterValidationError({\n provider: PROVIDER,\n operation: \"sendTurn\",\n issue: `OpenCode model selection is bound to instance '${modelSelection?.instanceId}', expected '${boundInstanceId}'.`,\n });\n }\n const parsedModel = parseOpenCodeModelSlug(modelSelection?.model);\n if (!parsedModel) {\n return yield* new ProviderAdapterValidationError({\n provider: PROVIDER,\n operation: \"sendTurn\",\n issue: \"OpenCode model selection must use the 'provider/model' format.\",\n });\n }\n\n const text = input.input?.trim();\n const fileParts = toOpenCodeFileParts({\n attachments: input.attachments,\n resolveAttachmentPath: (attachment) =>\n resolveAttachmentPath({\n attachmentsDir: serverConfig.attachmentsDir,\n attachment,\n }),\n });\n if ((!text || text.length === 0) && fileParts.length === 0) {\n return yield* new ProviderAdapterValidationError({\n provider: PROVIDER,\n operation: \"sendTurn\",\n issue: \"OpenCode turns require text input or at least one attachment.\",\n });\n }\n\n const agent = getModelSelectionStringOptionValue(modelSelection, \"agent\");\n const variant = getModelSelectionStringOptionValue(modelSelection, \"variant\");\n\n context.activeTurnId = turnId;\n context.activeAgent = agent ?? (input.interactionMode === \"plan\" ? \"plan\" : undefined);\n context.activeVariant = variant;\n yield* updateProviderSession(\n context,\n {\n status: \"running\",\n activeTurnId: turnId,\n model: modelSelection?.model ?? context.session.model,\n },\n { clearLastError: true },\n );\n\n if (steeringTurnId === undefined) {\n yield* emit({\n ...(yield* buildEventBase({ threadId: input.threadId, turnId })),\n type: \"turn.started\",\n payload: {\n model: modelSelection?.model ?? context.session.model,\n ...(variant ? { effort: variant } : {}),\n },\n });\n }\n\n yield* runOpenCodeSdk(\"session.promptAsync\", () =>\n context.client.session.promptAsync({\n sessionID: context.openCodeSessionId,\n model: parsedModel,\n ...(context.activeAgent ? { agent: context.activeAgent } : {}),\n ...(context.activeVariant ? { variant: context.activeVariant } : {}),\n parts: [...(text ? [{ type: \"text\" as const, text }] : []), ...fileParts],\n }),", + "checksum": "bd23ad46a4ad8ad0613a82192a06a3329c10808cfda57391fd77f2ba14fcccf9" + }, + "usage-live-contract": { + "id": "usage-live-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 309, + "end": 331, + "language": "typescript", + "label": "Live thread token-usage snapshot contract", + "code": "export const ThreadTokenUsageSnapshot = Schema.Struct({\n usedTokens: NonNegativeInt,\n totalProcessedTokens: Schema.optional(NonNegativeInt),\n maxTokens: Schema.optional(PositiveInt),\n inputTokens: Schema.optional(NonNegativeInt),\n cachedInputTokens: Schema.optional(NonNegativeInt),\n outputTokens: Schema.optional(NonNegativeInt),\n reasoningOutputTokens: Schema.optional(NonNegativeInt),\n lastUsedTokens: Schema.optional(NonNegativeInt),\n lastInputTokens: Schema.optional(NonNegativeInt),\n lastCachedInputTokens: Schema.optional(NonNegativeInt),\n lastOutputTokens: Schema.optional(NonNegativeInt),\n lastReasoningOutputTokens: Schema.optional(NonNegativeInt),\n toolUses: Schema.optional(NonNegativeInt),\n durationMs: Schema.optional(NonNegativeInt),\n compactsAutomatically: Schema.optional(Schema.Boolean),\n});\nexport type ThreadTokenUsageSnapshot = typeof ThreadTokenUsageSnapshot.Type;\n\nconst ThreadTokenUsageUpdatedPayload = Schema.Struct({\n usage: ThreadTokenUsageSnapshot,\n});\nexport type ThreadTokenUsageUpdatedPayload = typeof ThreadTokenUsageUpdatedPayload.Type;", + "checksum": "d63a433efcb36c6017efca4dfa4c29f8e8186b060316152534c0befba263d700" + }, + "usage-codex-normalization": { + "id": "usage-codex-normalization", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 159, + "end": 190, + "language": "typescript", + "label": "Codex live token-usage normalization", + "code": "function normalizeCodexTokenUsage(\n usage: EffectCodexSchema.V2ThreadTokenUsageUpdatedNotification[\"tokenUsage\"],\n): ThreadTokenUsageSnapshot | undefined {\n const totalProcessedTokens = usage.total.totalTokens;\n const usedTokens = usage.last.totalTokens;\n if (usedTokens === undefined || usedTokens <= 0) {\n return undefined;\n }\n\n const maxTokens = usage.modelContextWindow ?? undefined;\n const inputTokens = usage.last.inputTokens;\n const cachedInputTokens = usage.last.cachedInputTokens;\n const outputTokens = usage.last.outputTokens;\n const reasoningOutputTokens = usage.last.reasoningOutputTokens;\n\n return {\n usedTokens,\n ...(totalProcessedTokens !== undefined && totalProcessedTokens > usedTokens\n ? { totalProcessedTokens }\n : {}),\n ...(maxTokens !== undefined ? { maxTokens } : {}),\n ...(inputTokens !== undefined ? { inputTokens } : {}),\n ...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),\n ...(outputTokens !== undefined ? { outputTokens } : {}),\n ...(reasoningOutputTokens !== undefined ? { reasoningOutputTokens } : {}),\n ...(usedTokens !== undefined ? { lastUsedTokens: usedTokens } : {}),\n ...(inputTokens !== undefined ? { lastInputTokens: inputTokens } : {}),\n ...(cachedInputTokens !== undefined ? { lastCachedInputTokens: cachedInputTokens } : {}),\n ...(outputTokens !== undefined ? { lastOutputTokens: outputTokens } : {}),\n ...(reasoningOutputTokens !== undefined\n ? { lastReasoningOutputTokens: reasoningOutputTokens }\n : {}),", + "checksum": "fec887f108f8d86e020a989334ff325a8b42f40bb30b26f61e69fe87041df522" + }, + "usage-codex-emission": { + "id": "usage-codex-emission", + "path": "apps/server/src/provider/Layers/CodexAdapter.ts", + "start": 1000, + "end": 1018, + "language": "typescript", + "label": "Codex live usage event emission", + "code": " if (event.method === \"thread/tokenUsage/updated\") {\n const payload = readPayload(\n EffectCodexSchema.V2ThreadTokenUsageUpdatedNotification,\n event.payload,\n );\n const normalizedUsage = payload ? normalizeCodexTokenUsage(payload.tokenUsage) : undefined;\n if (!normalizedUsage) {\n return [];\n }\n return [\n {\n type: \"thread.token-usage.updated\",\n ...runtimeEventBase(event, canonicalThreadId),\n payload: {\n usage: normalizedUsage,\n },\n },\n ];\n }", + "checksum": "b5443e4a9d8358ced1bc548a51227ab8796667482f262f5ebc6513cda5220cf1" + }, + "usage-claude-emission": { + "id": "usage-claude-emission", + "path": "apps/server/src/provider/Layers/ClaudeAdapter.ts", + "start": 2051, + "end": 2088, + "language": "typescript", + "label": "Claude live usage event emission", + "code": " const emitThreadTokenUsage = Effect.fn(\"emitThreadTokenUsage\")(function* (\n context: ClaudeSessionContext,\n usage: ThreadTokenUsageSnapshot | undefined,\n options?: {\n readonly rawMethod?: string;\n readonly rawPayload?: unknown;\n },\n ) {\n if (!usage) {\n return;\n }\n\n context.lastKnownTokenUsage = usage;\n context.lastKnownTotalProcessedTokens =\n usage.totalProcessedTokens ?? context.lastKnownTotalProcessedTokens;\n\n const turnState = context.turnState;\n const stamp = yield* makeEventStamp();\n yield* offerRuntimeEvent({\n type: \"thread.token-usage.updated\",\n eventId: stamp.eventId,\n provider: PROVIDER,\n createdAt: stamp.createdAt,\n threadId: context.session.threadId,\n ...(turnState ? { turnId: turnState.turnId } : {}),\n payload: {\n usage,\n },\n providerRefs: nativeProviderRefs(context),\n ...(options?.rawMethod || options?.rawPayload\n ? {\n raw: {\n source: \"claude.sdk.message\" as const,\n ...(options.rawMethod ? { method: options.rawMethod } : {}),\n payload: options.rawPayload,\n },\n }\n : {}),", + "checksum": "1358344a9ecfbb8fb89639a941e39879abdeb0f8da803ccfa6e9b66cb69478f1" + }, + "usage-live-activity": { + "id": "usage-live-activity", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 766, + "end": 784, + "language": "typescript", + "label": "Live usage becomes context-window activity", + "code": " case \"thread.token-usage.updated\": {\n const payload = buildContextWindowActivityPayload(event);\n if (!payload) {\n return [];\n }\n\n return [\n {\n id: event.eventId,\n createdAt: event.createdAt,\n tone: \"info\",\n kind: \"context-window.updated\",\n summary: \"Context window updated\",\n payload,\n turnId: toTurnId(event.turnId) ?? null,\n ...maybeSequence,\n },\n ];\n }", + "checksum": "32de8fdc5bf965dcd67f6e3ebef7b896b6605e8c2a5d2d0a5544a915dccf9c1e" + }, + "usage-web-context-meter": { + "id": "usage-web-context-meter", + "path": "apps/web/src/lib/contextWindow.ts", + "start": 50, + "end": 96, + "language": "typescript", + "label": "Latest valid context-window snapshot derivation", + "code": "export function deriveLatestContextWindowSnapshot(\n activities: ReadonlyArray,\n): ContextWindowSnapshot | null {\n for (let index = activities.length - 1; index >= 0; index -= 1) {\n const activity = activities[index];\n if (!activity || activity.kind !== \"context-window.updated\") {\n continue;\n }\n\n const payload = asRecord(activity.payload);\n const usedTokens = asFiniteNumber(payload?.usedTokens);\n if (usedTokens === null || usedTokens < 0) {\n continue;\n }\n\n const maxTokens = asFiniteNumber(payload?.maxTokens);\n const usedPercentage =\n maxTokens !== null && maxTokens > 0 ? Math.min(100, (usedTokens / maxTokens) * 100) : null;\n const remainingTokens =\n maxTokens !== null ? Math.max(0, Math.round(maxTokens - usedTokens)) : null;\n const remainingPercentage = usedPercentage !== null ? Math.max(0, 100 - usedPercentage) : null;\n\n return {\n usedTokens,\n totalProcessedTokens: asFiniteNumber(payload?.totalProcessedTokens),\n maxTokens,\n remainingTokens,\n usedPercentage,\n remainingPercentage,\n inputTokens: asFiniteNumber(payload?.inputTokens),\n cachedInputTokens: asFiniteNumber(payload?.cachedInputTokens),\n outputTokens: asFiniteNumber(payload?.outputTokens),\n reasoningOutputTokens: asFiniteNumber(payload?.reasoningOutputTokens),\n lastUsedTokens: asFiniteNumber(payload?.lastUsedTokens),\n lastInputTokens: asFiniteNumber(payload?.lastInputTokens),\n lastCachedInputTokens: asFiniteNumber(payload?.lastCachedInputTokens),\n lastOutputTokens: asFiniteNumber(payload?.lastOutputTokens),\n lastReasoningOutputTokens: asFiniteNumber(payload?.lastReasoningOutputTokens),\n toolUses: asFiniteNumber(payload?.toolUses),\n durationMs: asFiniteNumber(payload?.durationMs),\n compactsAutomatically: asBoolean(payload?.compactsAutomatically) ?? false,\n updatedAt: activity.createdAt,\n };\n }\n\n return null;\n}", + "checksum": "f414738aaad3b6f8526e5760a436944757fefe35662bb9ce36fe9375f1c0c35b" + }, + "usage-summary-contract": { + "id": "usage-summary-contract", + "path": "packages/contracts/src/usage.ts", + "start": 1, + "end": 101, + "language": "typescript", + "label": "Historical usage version, providers, tokens, and cost buckets", + "code": "/**\n * Usage reporting contract.\n *\n * Each environment scans the provider CLIs' own on-disk session transcripts\n * (`~/.claude/projects/**\\/*.jsonl`, `~/.codex/sessions/**\\/*.jsonl`) rather than\n * relying on T3 Code's own orchestration projections, so usage stays complete\n * even for turns that were never driven through T3 Code. This mirrors the\n * approach `ccusage` takes.\n *\n * Environments return pre-aggregated `(day, hourStart?, provider, model)`\n * buckets. Raw transcript records never cross the wire.\n *\n * @module usage\n */\nimport * as Schema from \"effect/Schema\";\n\nimport { NonNegativeInt, TrimmedNonEmptyString } from \"./baseSchemas.ts\";\n\n/**\n * Bumped whenever the shape of {@link UsageSummary} changes incompatibly. The\n * client renders partial coverage when an environment reports an older version\n * rather than failing the whole page.\n */\nexport const USAGE_CONTRACT_VERSION = 4 as const;\n\nexport const UsageProviderKind = Schema.Literals([\"claude\", \"codex\"]);\nexport type UsageProviderKind = typeof UsageProviderKind.Type;\n\n/**\n * A calendar day in the reporting time zone, formatted `YYYY-MM-DD`.\n *\n * Days are bucketed server-side so that a turn always lands on the day the user\n * experienced it, not the UTC day.\n */\nconst USAGE_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const UsageDay = TrimmedNonEmptyString.check(Schema.isPattern(USAGE_DAY_PATTERN)).pipe(\n Schema.brand(\"UsageDay\"),\n);\nexport type UsageDay = typeof UsageDay.Type;\n\nexport const UsageResolution = Schema.Literals([\"day\", \"hour\"]);\nexport type UsageResolution = typeof UsageResolution.Type;\n\n/**\n * Why a bucket's cost is what it is.\n *\n * - `providerReported` - the transcript carried an explicit cost figure.\n * - `modelPriced` - we matched the model against the LiteLLM rate table.\n * - `unpriced` - tokens are known, rates are not. Counted in totals, excluded\n * from cost.\n */\nexport const UsageCostSource = Schema.Literals([\"providerReported\", \"modelPriced\", \"unpriced\"]);\nexport type UsageCostSource = typeof UsageCostSource.Type;\n\n/**\n * Token counts for a bucket.\n *\n * `cachedInputTokens` and `cacheCreationTokens` are disjoint from\n * `uncachedInputTokens`; summing all three gives total input. `reasoningTokens`\n * is a *subset* of `outputTokens` (Codex reports it that way, and Anthropic\n * folds thinking into output), so it must never be added on top.\n */\nexport const UsageTokenTotals = Schema.Struct({\n uncachedInputTokens: NonNegativeInt,\n cachedInputTokens: NonNegativeInt,\n cacheCreationTokens: NonNegativeInt,\n outputTokens: NonNegativeInt,\n reasoningTokens: NonNegativeInt,\n});\nexport type UsageTokenTotals = typeof UsageTokenTotals.Type;\n\n/**\n * One `(day, hourStart?, provider, model)` cell. `hourStart` is the UTC start\n * instant of a rolling bucket and is present only for hourly requests.\n *\n * `costUsd` is the raw API-equivalent cost of these tokens. It is not money\n * spent: subscription plans bill separately. `unpricedRecords` counts records\n * whose tokens are included in the token totals but which contributed nothing\n * to `costUsd`.\n */\nexport const UsageBucket = Schema.Struct({\n day: UsageDay,\n hourStart: Schema.optional(TrimmedNonEmptyString),\n provider: UsageProviderKind,\n model: TrimmedNonEmptyString,\n totals: UsageTokenTotals,\n costUsd: Schema.Number,\n /**\n * What the cached input would have cost at full input rates minus what it\n * actually cost. Requires the rate table, so it is computed alongside cost\n * rather than derived on the client.\n */\n cacheSavingsUsd: Schema.Number,\n costSource: UsageCostSource,\n /** Distinct assistant responses, after de-duplication. */\n records: NonNegativeInt,\n unpricedRecords: NonNegativeInt,\n /** Distinct transcript sessions that contributed to this cell. */\n sessions: NonNegativeInt,\n});", + "checksum": "f93dd8ada5db38b9c283d950acc7da22def26fa5c8ae2352aca8ab2aa31b3040" + }, + "usage-home-discovery": { + "id": "usage-home-discovery", + "path": "apps/server/src/usage/UsageService.ts", + "start": 187, + "end": 225, + "language": "typescript", + "label": "Claude and Codex transcript home resolution", + "code": " /**\n * Claude's config dir is the home itself when overridden, but a default\n * install nests transcripts under `~/.claude/projects`. Probe both.\n */\n const resolveClaudeTranscriptDir = (homePath: string) =>\n Effect.gen(function* () {\n const nested = path.join(homePath, \".claude\", \"projects\");\n const nestedExists = yield* fileSystem\n .exists(nested)\n .pipe(Effect.catchCause(() => Effect.succeed(false)));\n return nestedExists ? nested : path.join(homePath, \"projects\");\n });\n\n /** Resolves the transcript directory for each provider. */\n const resolveTranscriptDirs = Effect.fn(\"UsageService.resolveTranscriptDirs\")(function* () {\n // A settings failure must surface as an error: swallowing it here would\n // present \"zero usage from every provider\" as a valid answer.\n const settings = yield* settingsService.getSettings.pipe(\n Effect.catchCause(\n (cause) =>\n new UsageReadError({\n reason: \"scanFailed\",\n // Bounded description; the squashed failure travels as the cause.\n // Squashed, not the Cause tree: a full tree in a Defect field is\n // the unbounded wire payload the bounded detail exists to avoid.\n detail: \"Server settings could not be read.\",\n cause: Cause.squash(cause),\n }),\n ),\n );\n\n const claudeHome = yield* resolveClaudeHomePath(settings.providers.claudeAgent);\n const claudeDir = yield* resolveClaudeTranscriptDir(claudeHome);\n const codexLayout = yield* resolveCodexHomeLayout(settings.providers.codex);\n\n return [\n { provider: \"claude\" as const, dir: claudeDir },\n { provider: \"codex\" as const, dir: path.join(codexLayout.sharedHomePath, \"sessions\") },\n ];", + "checksum": "d6526ea3f89bb7c8877e0d60c06a6f36809be5b51834b133045a40debecabafd" + }, + "usage-transcript-parsers": { + "id": "usage-transcript-parsers", + "path": "apps/server/src/usage/usageTranscripts.ts", + "start": 78, + "end": 137, + "language": "typescript", + "label": "Claude transcript usage normalization", + "code": "/**\n * Parses one line of a Claude Code transcript.\n *\n * T3 Code writes one record per assistant *content block*, and every one of\n * those records repeats the same complete `usage` object for the parent\n * message. Summing them overcounts by roughly 2.4x on a real workload, so the\n * caller must drop repeats by `dedupeKey` and keep the first.\n */\nexport function parseClaudeLine(line: string): UsageRecord | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) return null;\n\n const record = parsed as Record;\n if (record[\"type\"] !== \"assistant\") return null;\n\n const message = record[\"message\"];\n if (typeof message !== \"object\" || message === null) return null;\n const messageRecord = message as Record;\n\n const usage = messageRecord[\"usage\"];\n if (typeof usage !== \"object\" || usage === null) return null;\n const usageRecord = usage as Record;\n\n const timestampMs = parseTimestampMs(record[\"timestamp\"]);\n if (timestampMs === null) return null;\n\n const model = typeof messageRecord[\"model\"] === \"string\" ? messageRecord[\"model\"] : \"\";\n if (model.length === 0) return null;\n\n const messageId = typeof messageRecord[\"id\"] === \"string\" ? messageRecord[\"id\"] : null;\n const requestId = typeof record[\"requestId\"] === \"string\" ? record[\"requestId\"] : null;\n // Matches ccusage: prefer the message/request pair, fall back to whichever\n // half exists. Records with neither cannot be de-duplicated.\n const dedupeKey =\n messageId === null && requestId === null ? null : `${messageId ?? \"\"}:${requestId ?? \"\"}`;\n\n const cost = record[\"costUSD\"];\n\n return {\n provider: \"claude\",\n timestampMs,\n model,\n sessionId: typeof record[\"sessionId\"] === \"string\" ? record[\"sessionId\"] : \"\",\n totals: {\n uncachedInputTokens: int(usageRecord[\"input_tokens\"]),\n cachedInputTokens: int(usageRecord[\"cache_read_input_tokens\"]),\n cacheCreationTokens: int(usageRecord[\"cache_creation_input_tokens\"]),\n outputTokens: int(usageRecord[\"output_tokens\"]),\n // Anthropic folds thinking tokens into output and does not break them out.\n reasoningTokens: 0,\n },\n reportedCostUsd: typeof cost === \"number\" && Number.isFinite(cost) ? cost : null,\n dedupeKey,\n };\n}", + "checksum": "98addede4c92886630a8f69b8ec46e776ac775bbb00896814ba7a17e244c4531" + }, + "usage-dedup-buckets": { + "id": "usage-dedup-buckets", + "path": "apps/server/src/usage/usageAggregation.ts", + "start": 109, + "end": 178, + "language": "typescript", + "label": "Global deduplication, bounds, bucketing, and pricing fold", + "code": " /**\n * Folds one record in. Returns whether it actually contributed, so callers\n * can derive per-window facts (distinct sessions, for one) from the records\n * that landed rather than everything the mtime prefilter happened to admit.\n */\n add(record: UsageRecord): boolean {\n if (record.dedupeKey !== null) {\n if (this.#seen.has(record.dedupeKey)) {\n this.#duplicatesDropped += 1;\n return false;\n }\n this.#seen.add(record.dedupeKey);\n }\n\n if (\n this.#hourlyWindow !== null &&\n (record.timestampMs < this.#hourlyWindow.sinceTimeMs ||\n record.timestampMs >= this.#hourlyWindow.untilTimeMs)\n ) {\n this.#outOfWindow += 1;\n return false;\n }\n\n const day = this.#toDay(record.timestampMs);\n if (\n this.#hourlyWindow === null &&\n (day < this.#options.sinceDay || day > this.#options.untilDay)\n ) {\n this.#outOfWindow += 1;\n return false;\n }\n\n const hourStart =\n this.#hourlyWindow === null\n ? \"\"\n : new Date(\n this.#hourlyWindow.sinceTimeMs +\n Math.floor((record.timestampMs - this.#hourlyWindow.sinceTimeMs) / HOUR_MS) * HOUR_MS,\n ).toISOString();\n const key = `${day}\\u0000${hourStart}\\u0000${record.provider}\\u0000${record.model}`;\n let bucket = this.#buckets.get(key);\n if (bucket === undefined) {\n bucket = {\n totals: EMPTY_TOTALS,\n costUsd: 0,\n cacheSavingsUsd: 0,\n records: 0,\n unpricedRecords: 0,\n providerReportedRecords: 0,\n sessions: new Set(),\n };\n this.#buckets.set(key, bucket);\n }\n\n const priced = priceUsage(\n this.#options.rates,\n record.model,\n record.totals,\n record.reportedCostUsd,\n );\n\n bucket.totals = addTotals(bucket.totals, record.totals);\n bucket.costUsd += priced.costUsd;\n bucket.cacheSavingsUsd += cacheSavingsUsd(this.#options.rates, record.model, record.totals);\n bucket.records += 1;\n if (priced.costSource === \"unpriced\") bucket.unpricedRecords += 1;\n if (priced.costSource === \"providerReported\") bucket.providerReportedRecords += 1;\n if (record.sessionId.length > 0) bucket.sessions.add(record.sessionId);\n return true;\n }", + "checksum": "ca4bb237d353ca5cbf384f3e91c0d802c24e1764b19871add182ac894cc19677" + }, + "usage-pricing-cache": { + "id": "usage-pricing-cache", + "path": "apps/server/src/usage/usagePricing.ts", + "start": 85, + "end": 148, + "language": "typescript", + "label": "Historical usage rate lookup and pricing arithmetic", + "code": "/**\n * Models we never price, regardless of the table.\n *\n * `` marks locally generated messages that were never billed. Bare\n * family names (\"opus\", \"sonnet\") are genuinely ambiguous across generations,\n * so we report them as unpriced instead of guessing a generation.\n */\nconst UNPRICEABLE_MODELS = new Set([\n \"\",\n \"synthetic\",\n \"opus\",\n \"sonnet\",\n \"haiku\",\n \"fable\",\n]);\n\nexport function lookupRate(table: RateTable, model: string): ModelRate | null {\n const normalized = normalizeModelName(model);\n if (normalized.length === 0 || UNPRICEABLE_MODELS.has(normalized)) return null;\n return table.get(normalized) ?? null;\n}\n\nexport interface PricedUsage {\n readonly costUsd: number;\n readonly costSource: UsageCostSource;\n}\n\n/**\n * Prices a bucket's tokens.\n *\n * `reasoningTokens` is intentionally not charged separately: it is already\n * counted inside `outputTokens`.\n */\nexport function priceUsage(\n table: RateTable,\n model: string,\n totals: UsageTokenTotals,\n reportedCostUsd: number | null,\n): PricedUsage {\n if (reportedCostUsd !== null && Number.isFinite(reportedCostUsd)) {\n return { costUsd: reportedCostUsd, costSource: \"providerReported\" };\n }\n\n const rate = lookupRate(table, model);\n if (rate === null) return { costUsd: 0, costSource: \"unpriced\" };\n\n const costUsd =\n totals.uncachedInputTokens * rate.inputCostPerToken +\n totals.cachedInputTokens * rate.cacheReadCostPerToken +\n totals.cacheCreationTokens * rate.cacheCreationCostPerToken +\n totals.outputTokens * rate.outputCostPerToken;\n\n return { costUsd, costSource: \"modelPriced\" };\n}\n\n/**\n * What the cached input would have cost at full input rates, minus what it\n * actually cost. Drives the \"cache savings\" figure.\n */\nexport function cacheSavingsUsd(table: RateTable, model: string, totals: UsageTokenTotals): number {\n const rate = lookupRate(table, model);\n if (rate === null) return 0;\n return totals.cachedInputTokens * (rate.inputCostPerToken - rate.cacheReadCostPerToken);\n}", + "checksum": "c1d6f1e6a20765222fbbd5c94a90766711a846430088f37c1242011fd9ec1518" + }, + "usage-rpc-contract": { + "id": "usage-rpc-contract", + "path": "packages/contracts/src/rpc.ts", + "start": 260, + "end": 284, + "language": "typescript", + "label": "Typed usage summary RPC", + "code": " previewAutomationFocusHost: \"previewAutomation.focusHost\",\n\n // Server meta\n serverProbe: \"server.probe\",\n serverGetConfig: \"server.getConfig\",\n serverRefreshProviders: \"server.refreshProviders\",\n serverUpdateProvider: \"server.updateProvider\",\n serverUpdateServer: \"server.updateServer\",\n serverUpdateServerWithProgress: \"server.updateServerWithProgress\",\n serverUpsertKeybinding: \"server.upsertKeybinding\",\n serverRemoveKeybinding: \"server.removeKeybinding\",\n serverGetSettings: \"server.getSettings\",\n serverUpdateSettings: \"server.updateSettings\",\n serverDiscoverSourceControl: \"server.discoverSourceControl\",\n serverGetTraceDiagnostics: \"server.getTraceDiagnostics\",\n serverGetProcessDiagnostics: \"server.getProcessDiagnostics\",\n serverGetProcessResourceHistory: \"server.getProcessResourceHistory\",\n serverGetResourceTelemetryHistory: \"server.getResourceTelemetryHistory\",\n serverRetryResourceTelemetry: \"server.retryResourceTelemetry\",\n serverSignalProcess: \"server.signalProcess\",\n serverReportClientActivity: \"server.reportClientActivity\",\n serverReportHostPowerState: \"server.reportHostPowerState\",\n serverGetBackgroundPolicy: \"server.getBackgroundPolicy\",\n serverGetUsageSummary: \"server.getUsageSummary\",\n", + "checksum": "a9bdb475c42adc730d43788b4336aa36b6c0de90e60fc9dcd2139b1f929e9ea6" + }, + "usage-environment-merge": { + "id": "usage-environment-merge", + "path": "packages/shared/src/usageMerge.ts", + "start": 102, + "end": 163, + "language": "typescript", + "label": "Deterministic physical-source ownership across environments", + "code": "/**\n * Decides which environment owns each physical transcript directory.\n *\n * Several environments on one machine (worktree servers, for instance) resolve\n * the same provider home and would otherwise double count every token. The\n * first environment in a stable order claims a fingerprint; the rest have that\n * provider's buckets dropped. Environments are sorted by id so the winner does\n * not change between renders.\n */\nfunction claimSources(environments: readonly EnvironmentUsage[]): {\n readonly ownerByFingerprint: ReadonlyMap;\n readonly duplicates: readonly string[];\n} {\n const ownerByFingerprint = new Map();\n const duplicates: string[] = [];\n\n const ordered = [...environments].sort((a, b) => a.environmentId.localeCompare(b.environmentId));\n\n for (const environment of ordered) {\n for (const source of environment.summary.sources) {\n if (source.status === \"missing\") continue;\n const key = fingerprintKey(source.fingerprint);\n if (ownerByFingerprint.has(key)) {\n duplicates.push(`${environment.label}: ${source.fingerprint.resolvedHomePath}`);\n continue;\n }\n ownerByFingerprint.set(key, environment.environmentId);\n }\n }\n\n return { ownerByFingerprint, duplicates };\n}\n\n/** Sources this environment owns after fingerprint claims, plus their buckets. */\nfunction ownedContribution(\n environment: EnvironmentUsage,\n ownerByFingerprint: ReadonlyMap,\n): {\n readonly buckets: readonly UsageBucket[];\n readonly sessionsByProvider: ReadonlyMap;\n} {\n const ownedProviders = new Set();\n const sessionsByProvider = new Map();\n for (const source of environment.summary.sources) {\n if (source.status === \"missing\") continue;\n const key = fingerprintKey(source.fingerprint);\n if (ownerByFingerprint.get(key) === environment.environmentId) {\n const provider = source.fingerprint.provider;\n ownedProviders.add(provider);\n // Distinct within a directory. Summing per-bucket session counts instead\n // would count a session once per day and model it spans.\n sessionsByProvider.set(\n provider,\n (sessionsByProvider.get(provider) ?? 0) + source.distinctSessions,\n );\n }\n }\n return {\n buckets: environment.summary.buckets.filter((bucket) => ownedProviders.has(bucket.provider)),\n sessionsByProvider,\n };\n}", + "checksum": "2ef3c27f0875e553cc334289b2ffa24682b812e8a15f401be76eb06240ccfb98" + }, + "usage-reader-failure-policy": { + "id": "usage-reader-failure-policy", + "path": "apps/server/src/usage/usageTranscriptReader.ts", + "start": 92, + "end": 140, + "language": "typescript", + "label": "Streaming transcript read and null-on-read-failure policy", + "code": "/**\n * Streams one transcript and returns the usage records it contains, or `null`\n * when the file could not be read.\n *\n * The distinction matters to the caller's cache: a genuinely empty transcript\n * is a stable fact worth memoising, while a transient read failure memoised\n * under the same `(size, mtime)` key would silently drop that file's usage\n * until the file next changes.\n *\n * Codex carries the active model on `turn_context` lines that hold no usage of\n * their own, so those still have to pass through the reducer to keep model\n * attribution correct.\n */\nexport async function readTranscriptRecords(\n filePath: string,\n provider: UsageProviderKind,\n): Promise {\n const records: UsageRecord[] = [];\n const codexState = initialCodexScanState();\n\n try {\n const lines = NodeReadline.createInterface({\n input: NodeFS.createReadStream(filePath, { encoding: \"utf8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of lines) {\n if (provider === \"codex\") {\n if (\n !mightCarryUsage(line, provider) &&\n !line.includes('\"turn_context\"') &&\n !line.includes('\"session_meta\"')\n ) {\n continue;\n }\n const record = parseCodexLine(line, codexState);\n if (record !== null) records.push(record);\n continue;\n }\n\n if (!mightCarryUsage(line, provider)) continue;\n const record = parseClaudeLine(line);\n if (record !== null) records.push(record);\n }\n } catch {\n return null;\n }\n\n return records;", + "checksum": "a4603871e61cae2e5575a2df75f84ff9f5684262b1cb59e638f3009e66fdfa58" + }, + "usage-source-status": { + "id": "usage-source-status", + "path": "apps/server/src/usage/UsageService.ts", + "start": 352, + "end": 408, + "language": "typescript", + "label": "Current historical source status and session accounting", + "code": " const sources: UsageSource[] = [];\n const livePaths = new Set();\n const walkedRoots: string[] = [];\n\n for (const { provider, dir } of dirs) {\n const volumeId = yield* Effect.promise(() => readDirectoryVolumeId(dir));\n const exists = yield* fileSystem\n .exists(dir)\n .pipe(Effect.catchCause(() => Effect.succeed(false)));\n\n if (!exists) {\n sources.push({\n fingerprint: { hostId, provider, resolvedHomePath: dir, volumeId },\n status: \"missing\",\n scannedFiles: 0,\n skippedFiles: 0,\n malformedRecords: 0,\n distinctSessions: 0,\n message: \"No transcript directory on this environment.\",\n });\n continue;\n }\n\n walkedRoots.push(dir);\n const files = yield* Effect.promise(() => listTranscriptFiles(dir, windowStartMs));\n let scannedFiles = 0;\n let skippedFiles = 0;\n // Distinct per directory. Buckets carry per-cell session counts, but a\n // session spans days and models, so clients total this figure instead.\n const sessionIds = new Set();\n\n for (const file of files) {\n livePaths.add(file.path);\n const records = yield* readFileRecords(file.path, file.size, file.mtimeMs, provider);\n if (records.length === 0) {\n skippedFiles += 1;\n continue;\n }\n scannedFiles += 1;\n for (const record of records) {\n // Only sessions that contributed in-window count: the mtime slack\n // admits boundary files whose records fall outside the range.\n if (aggregator.add(record) && record.sessionId.length > 0) {\n sessionIds.add(record.sessionId);\n }\n }\n }\n\n sources.push({\n fingerprint: { hostId, provider, resolvedHomePath: dir, volumeId },\n status: \"ok\",\n scannedFiles,\n skippedFiles,\n malformedRecords: 0,\n distinctSessions: sessionIds.size,\n message: null,\n });", + "checksum": "619a5fb4c66a09b2bf6abed238f22779341b997262bc48736bd927aa19f042f1" + }, + "project-root-normalization": { + "id": "project-root-normalization", + "path": "apps/server/src/workspace/WorkspacePaths.ts", + "start": 161, + "end": 200, + "language": "typescript", + "label": "Workspace-root resolution, validation, and opt-in creation", + "code": " const normalizeWorkspaceRoot: WorkspacePaths[\"Service\"][\"normalizeWorkspaceRoot\"] = Effect.fn(\n \"WorkspacePaths.normalizeWorkspaceRoot\",\n )(function* (workspaceRoot, options) {\n const normalizedWorkspaceRoot = path.resolve(expandHomePath(workspaceRoot.trim(), path));\n let workspaceStat = yield* statWorkspaceRoot(\n workspaceRoot,\n normalizedWorkspaceRoot,\n \"validate-existing\",\n );\n if (!workspaceStat && options?.createIfMissing) {\n yield* fileSystem.makeDirectory(normalizedWorkspaceRoot, { recursive: true }).pipe(\n Effect.mapError(\n (cause) =>\n new WorkspaceRootCreateFailedError({\n workspaceRoot,\n normalizedWorkspaceRoot,\n cause,\n }),\n ),\n );\n workspaceStat = yield* statWorkspaceRoot(\n workspaceRoot,\n normalizedWorkspaceRoot,\n \"verify-created\",\n );\n }\n if (!workspaceStat) {\n return yield* new WorkspaceRootNotExistsError({\n workspaceRoot,\n normalizedWorkspaceRoot,\n });\n }\n if (workspaceStat.type !== \"Directory\") {\n return yield* new WorkspaceRootNotDirectoryError({\n workspaceRoot,\n normalizedWorkspaceRoot,\n });\n }\n return normalizedWorkspaceRoot;\n });", + "checksum": "dc1befa9f427fd48c5c9988360c52a9532a82d89a2e243b0dee2c25f2794fc12" + }, + "project-create-normalization": { + "id": "project-create-normalization", + "path": "apps/server/src/orchestration/Normalizer.ts", + "start": 55, + "end": 90, + "language": "typescript", + "label": "Project creation normalization before dispatch", + "code": " const normalizeProjectWorkspaceRoot = (workspaceRoot: string) =>\n workspacePaths.normalizeWorkspaceRoot(workspaceRoot).pipe(\n Effect.mapError(\n (cause) =>\n new OrchestrationDispatchCommandError({\n message: cause.message,\n }),\n ),\n );\n\n const normalizeProjectWorkspaceRootForCreate = (\n workspaceRoot: string,\n createIfMissing: boolean | undefined,\n ) =>\n workspacePaths\n .normalizeWorkspaceRoot(workspaceRoot, {\n createIfMissing: createIfMissing === true,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new OrchestrationDispatchCommandError({\n message: cause.message,\n }),\n ),\n );\n\n if (canonicalCommand.type === \"project.create\") {\n return {\n ...canonicalCommand,\n workspaceRoot: yield* normalizeProjectWorkspaceRootForCreate(\n canonicalCommand.workspaceRoot,\n canonicalCommand.createWorkspaceRootIfMissing,\n ),\n createWorkspaceRootIfMissing: canonicalCommand.createWorkspaceRootIfMissing === true,\n } satisfies OrchestrationCommand;", + "checksum": "6b0a20d1e9548a92779defd07120ed3e684de23de08d6de2f159a36edf6b1f57" + }, + "project-root-uniqueness": { + "id": "project-root-uniqueness", + "path": "apps/server/src/orchestration/commandInvariants.ts", + "start": 75, + "end": 97, + "language": "typescript", + "label": "Active project workspace-root uniqueness invariant", + "code": "export function requireActiveProjectWorkspaceRootAbsent(input: {\n readonly readModel: OrchestrationReadModel;\n readonly command: OrchestrationCommand;\n readonly workspaceRoot: string;\n readonly exceptProjectId?: ProjectId;\n}): Effect.Effect {\n const normalizedWorkspaceRoot = normalizeProjectPathForComparison(input.workspaceRoot);\n const existingProject = input.readModel.projects.find(\n (project) =>\n project.deletedAt === null &&\n normalizeProjectPathForComparison(project.workspaceRoot) === normalizedWorkspaceRoot &&\n project.id !== input.exceptProjectId,\n );\n if (existingProject === undefined) {\n return Effect.void;\n }\n return Effect.fail(\n invariantError(\n input.command.type,\n `Active project '${existingProject.id}' already exists for workspace root '${normalizedWorkspaceRoot}'.`,\n ),\n );\n}", + "checksum": "deb6be62e500f8c6488c70dc0a2563c7f313722d5a4dc04e4c5e9aab21b4c134" + }, + "project-t3-file-schema": { + "id": "project-t3-file-schema", + "path": "packages/contracts/src/t3ProjectFile.ts", + "start": 7, + "end": 94, + "language": "typescript", + "label": "Checked-in t3.json project configuration contract", + "code": "/** File name of the checked-in T3 project file, resolved at the workspace root. */\nexport const T3_PROJECT_FILE_NAME = \"t3.json\";\n\n/** Public URL of the published JSON Schema for {@link T3ProjectFile}. */\nexport const T3_PROJECT_FILE_SCHEMA_URL = \"https://t3.codes/schema/t3.json\";\n\nconst T3_PROJECT_FILE_PATH_MAX_LENGTH = 512;\nconst T3_PROJECT_FILE_MAX_SCRIPTS = 50;\n\n// Annotations go on the encoded (string) side so they survive into the\n// published JSON Schema; decoding still trims and re-validates non-emptiness.\nconst trimmedNonEmpty = (annotations: { readonly description: string }, maxLength?: number) => {\n const annotated = Schema.String.annotate(annotations);\n const encoded =\n maxLength === undefined\n ? annotated.check(Schema.isNonEmpty())\n : annotated.check(Schema.isNonEmpty(), Schema.isMaxLength(maxLength));\n return encoded.pipe(Schema.decodeTo(encoded, SchemaTransformation.trim()));\n};\n\nexport const T3ProjectFileScript = Schema.Struct({\n name: trimmedNonEmpty({\n description: \"Display name for the script, shown in the T3 Code scripts menu.\",\n }),\n command: trimmedNonEmpty({\n description: \"Shell command executed in a T3 Code terminal at the project root.\",\n }),\n icon: Schema.optionalKey(\n ProjectScriptIcon.annotate({\n description: 'Icon shown next to the script in the scripts menu. Defaults to \"play\".',\n }),\n ),\n runOnWorktreeCreate: Schema.optionalKey(\n Schema.Boolean.annotate({\n description:\n \"When true, the script runs automatically after a worktree is created for a new thread.\",\n }),\n ),\n previewUrl: Schema.optionalKey(\n trimmedNonEmpty({\n description:\n \"URL opened in the in-app browser preview when this script runs. Only honored on the desktop build.\",\n }),\n ),\n autoOpenPreview: Schema.optionalKey(\n Schema.Boolean.annotate({\n description:\n \"When true, automatically open the preview panel at `previewUrl` the moment the script starts.\",\n }),\n ),\n}).annotate({\n description: \"A project script that team members can import into T3 Code.\",\n});\nexport type T3ProjectFileScript = typeof T3ProjectFileScript.Type;\n\nexport const T3ProjectFile = Schema.Struct({\n $schema: Schema.optionalKey(\n Schema.String.annotate({\n description: `URL of the JSON Schema for this file, typically \"${T3_PROJECT_FILE_SCHEMA_URL}\".`,\n }),\n ),\n iconPath: Schema.optionalKey(\n trimmedNonEmpty(\n {\n description:\n 'Workspace-relative path to the project icon (e.g. \"assets/logo.svg\"). Checked before T3 Code\\'s built-in icon locations.',\n },\n T3_PROJECT_FILE_PATH_MAX_LENGTH,\n ),\n ),\n defaultThreadEnvMode: Schema.optionalKey(\n ThreadEnvMode.annotate({\n description:\n 'Where new threads start for this repository: \"worktree\" for a fresh git worktree, \"local\" for the current checkout. A per-project setting in T3 Code overrides this; when neither is set, the global default applies.',\n }),\n ),\n scripts: Schema.optionalKey(\n Schema.Array(T3ProjectFileScript)\n .annotate({\n description: \"Project scripts shared with everyone who opens this repository in T3 Code.\",\n })\n .check(Schema.isMaxLength(T3_PROJECT_FILE_MAX_SCRIPTS)),\n ),\n}).annotate({\n title: \"T3 project file\",\n description:\n \"Checked-in project configuration for T3 Code (t3.json at the repository root). See https://t3.codes for documentation.\",\n});", + "checksum": "9b60c876a679d515b8a414916f3f37d5b8e502a68d55df9d21ee476d8cb4e379" + }, + "project-t3-file-loader": { + "id": "project-t3-file-loader", + "path": "apps/server/src/project/T3ProjectFileLoader.ts", + "start": 42, + "end": 105, + "language": "typescript", + "label": "Best-effort t3.json loading and validation", + "code": " /**\n * Load and decode `t3.json` at the workspace root.\n *\n * Never fails: missing, unreadable, or invalid files resolve to\n * `Option.none` (invalid files are logged as warnings).\n */\n readonly load: (workspaceRoot: string) => Effect.Effect>;\n }\n>()(\"t3/project/T3ProjectFileLoader\") {}\n\nconst logT3ProjectFileLoadError = (error: T3ProjectFileLoadError) =>\n Effect.logWarning(error).pipe(\n Effect.annotateLogs({\n operation: error.operation,\n workspaceRoot: error.workspaceRoot,\n filePath: error.filePath,\n errorTag: error._tag,\n }),\n );\n\nexport const make = Effect.gen(function* () {\n const fileSystem = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n\n const load: T3ProjectFileLoader[\"Service\"][\"load\"] = Effect.fn(\"T3ProjectFileLoader.load\")(\n function* (workspaceRoot) {\n const filePath = path.join(workspaceRoot, T3_PROJECT_FILE_NAME);\n const raw = yield* fileSystem.readFileString(filePath).pipe(\n Effect.map(Option.some),\n Effect.catchTags({\n PlatformError: (error) =>\n error.reason._tag === \"NotFound\"\n ? Effect.succeed(Option.none())\n : logT3ProjectFileLoadError(\n new T3ProjectFileLoadError({\n operation: \"read\",\n workspaceRoot,\n filePath,\n cause: error,\n }),\n ).pipe(Effect.as(Option.none())),\n }),\n );\n if (Option.isNone(raw)) {\n return Option.none();\n }\n return yield* decodeT3ProjectFileJson(raw.value).pipe(\n Effect.map(Option.some),\n Effect.catchTags({\n SchemaError: (error) =>\n logT3ProjectFileLoadError(\n new T3ProjectFileLoadError({\n operation: \"decode\",\n workspaceRoot,\n filePath,\n cause: error,\n }),\n ).pipe(Effect.as(Option.none())),\n }),\n );\n },\n );\n\n return T3ProjectFileLoader.of({ load });", + "checksum": "1a2c82901fba9d86213563abdee2569b7f48283533b7c7cc23b5bfd46b7df753" + }, + "project-t3-file-loader-tests": { + "id": "project-t3-file-loader-tests", + "path": "apps/server/src/project/T3ProjectFileLoader.test.ts", + "start": 29, + "end": 88, + "language": "typescript", + "label": "t3.json JSONC, missing-file, and invalid-input tests", + "code": "it.layer(TestLayer)(\"T3ProjectFileLoader\", (it) => {\n describe(\"load\", () => {\n it.effect(\"loads and decodes a valid t3.json\", () =>\n Effect.gen(function* () {\n const loader = yield* T3ProjectFileLoader.T3ProjectFileLoader;\n const cwd = yield* makeTempDir;\n yield* writeProjectFile(\n cwd,\n `{\n // JSONC is tolerated\n \"iconPath\": \"assets/logo.svg\",\n \"scripts\": [{ \"name\": \"Dev\", \"command\": \"pnpm dev\" }],\n }`,\n );\n\n const loaded = yield* loader.load(cwd);\n\n expect(Option.isSome(loaded)).toBe(true);\n if (Option.isSome(loaded)) {\n expect(loaded.value.iconPath).toBe(\"assets/logo.svg\");\n expect(loaded.value.scripts).toEqual([{ name: \"Dev\", command: \"pnpm dev\" }]);\n }\n }),\n );\n\n it.effect(\"returns none when t3.json is missing\", () =>\n Effect.gen(function* () {\n const loader = yield* T3ProjectFileLoader.T3ProjectFileLoader;\n const cwd = yield* makeTempDir;\n\n const loaded = yield* loader.load(cwd);\n\n expect(Option.isNone(loaded)).toBe(true);\n }),\n );\n\n it.effect(\"returns none for malformed JSON without failing\", () =>\n Effect.gen(function* () {\n const loader = yield* T3ProjectFileLoader.T3ProjectFileLoader;\n const cwd = yield* makeTempDir;\n yield* writeProjectFile(cwd, \"{ not json\");\n\n const loaded = yield* loader.load(cwd);\n\n expect(Option.isNone(loaded)).toBe(true);\n }),\n );\n\n it.effect(\"returns none for schema-invalid files without failing\", () =>\n Effect.gen(function* () {\n const loader = yield* T3ProjectFileLoader.T3ProjectFileLoader;\n const cwd = yield* makeTempDir;\n yield* writeProjectFile(cwd, '{ \"scripts\": [{ \"name\": \"Dev\" }] }');\n\n const loaded = yield* loader.load(cwd);\n\n expect(Option.isNone(loaded)).toBe(true);\n }),\n );\n });", + "checksum": "e86ba3069d84308153516d912b05407d54ea3630b7ad2b1a21efb1fe37fb344f" + }, + "project-thread-env-precedence": { + "id": "project-thread-env-precedence", + "path": "packages/shared/src/threadEnvMode.ts", + "start": 3, + "end": 35, + "language": "typescript", + "label": "Project, t3.json, and global thread-environment precedence", + "code": "/**\n * Canonical priority order for a project's default thread env mode:\n * per-project setting > checked-in t3.json > global server setting.\n *\n * An explicit composer pick outranks all of these; callers apply it before\n * consulting the defaults. Web resolves the sources imperatively at draft\n * creation, mobile reactively — both must route through this function so the\n * platforms cannot disagree on the order.\n */\nexport function resolveDefaultThreadEnvMode(sources: {\n readonly projectSetting: ThreadEnvMode | null | undefined;\n readonly projectFile: ThreadEnvMode | null | undefined;\n readonly globalDefault: ThreadEnvMode;\n}): ThreadEnvMode {\n return sources.projectSetting ?? sources.projectFile ?? sources.globalDefault;\n}\n\n/**\n * True once the resolved default can no longer change: an explicit pick or a\n * source that outranks t3.json decided, or the file read settled. While\n * false, nothing may persist the provisional default (for example into a\n * draft's workspace selection) — it could differ from the final value.\n */\nexport function isDefaultThreadEnvModeSettled(sources: {\n readonly explicitMode: ThreadEnvMode | undefined;\n readonly projectSetting: ThreadEnvMode | null | undefined;\n readonly projectFilePending: boolean;\n}): boolean {\n return (\n sources.explicitMode !== undefined ||\n sources.projectSetting != null ||\n !sources.projectFilePending\n );", + "checksum": "f92aec71fc3a12aa186ad667b7a2e1adb8ac4e560f6f6376511e4b0765ee7851" + }, + "project-settings-inherited-default": { + "id": "project-settings-inherited-default", + "path": "apps/web/src/components/settings/ProjectSettingsPanel.tsx", + "start": 475, + "end": 482, + "language": "tsx", + "label": "Inherited project environment default in web settings", + "code": " const t3File = useT3ProjectFileState(\n selectedCheckout.environmentId,\n selectedCheckout.workspaceRoot,\n );\n // What the \"Default\" option resolves to while no override is set: the\n // repo's t3.json value when present, otherwise the global setting.\n const inheritedEnvMode = t3File.file?.defaultThreadEnvMode ?? settings.defaultThreadEnvMode;\n const inheritedEnvModeSource = t3File.file?.defaultThreadEnvMode != null ? \"t3.json\" : \"global\";", + "checksum": "7ab6370096f28cd8e0175e8d2a40f3e7e4e29a087f725975228b5ffdff9f68a2" + }, + "project-settings-project-override": { + "id": "project-settings-project-override", + "path": "apps/web/src/components/settings/ProjectSettingsPanel.tsx", + "start": 866, + "end": 905, + "language": "tsx", + "label": "Project environment override controls", + "code": " setDefaultThreadEnvMode(null)}\n />\n ) : null\n }\n control={\n {\n if (value === \"worktree\" || value === \"local\") {\n setDefaultThreadEnvMode(value);\n } else if (value === \"inherit\") {\n setDefaultThreadEnvMode(null);\n }\n }}\n >\n \n \n {storedEnvMode === null\n ? group.memberProjects.length > 1\n ? \"Default (per checkout)\"\n : `Default (${resolveEnvModeLabel(inheritedEnvMode).toLowerCase()})`\n : resolveEnvModeLabel(storedEnvMode)}\n \n \n \n \n {group.memberProjects.length > 1\n ? \"Default (each checkout's t3.json or global setting)\"\n : `Default (${inheritedEnvModeSource}: ${resolveEnvModeLabel(inheritedEnvMode).toLowerCase()})`}\n \n {resolveEnvModeLabel(\"worktree\")}\n {resolveEnvModeLabel(\"local\")}\n ", + "checksum": "8bfa93d2fed3d5a4362c1c30abedf00d2d1811052808a02f9ec63ed3338c8d35" + }, + "project-repository-identity": { + "id": "project-repository-identity", + "path": "apps/server/src/project/RepositoryIdentityResolver.ts", + "start": 48, + "end": 166, + "language": "typescript", + "label": "Best-effort Git remote repository identity resolution", + "code": "function pickPrimaryRemote(\n remotes: ReadonlyMap,\n): { readonly remoteName: string; readonly remoteUrl: string } | null {\n for (const preferredRemoteName of [\"upstream\", \"origin\"] as const) {\n const remoteUrl = remotes.get(preferredRemoteName);\n if (remoteUrl) {\n return { remoteName: preferredRemoteName, remoteUrl };\n }\n }\n\n const [remoteName, remoteUrl] =\n [...remotes.entries()].toSorted(([left], [right]) => left.localeCompare(right))[0] ?? [];\n return remoteName && remoteUrl ? { remoteName, remoteUrl } : null;\n}\n\nfunction buildRepositoryIdentity(input: {\n readonly remoteName: string;\n readonly remoteUrl: string;\n readonly rootPath: string;\n}): RepositoryIdentity {\n const canonicalKey = normalizeGitRemoteUrl(input.remoteUrl);\n const sourceControlProvider = detectSourceControlProviderFromGitRemoteUrl(input.remoteUrl);\n const repositoryPath = canonicalKey.split(\"/\").slice(1).join(\"/\");\n const repositoryPathSegments = repositoryPath.split(\"/\").filter((segment) => segment.length > 0);\n const [owner] = repositoryPathSegments;\n const repositoryName = repositoryPathSegments.at(-1);\n\n return {\n canonicalKey,\n locator: {\n source: \"git-remote\",\n remoteName: input.remoteName,\n remoteUrl: input.remoteUrl,\n },\n rootPath: input.rootPath,\n ...(repositoryPath ? { displayName: repositoryPath } : {}),\n ...(sourceControlProvider ? { provider: sourceControlProvider.kind } : {}),\n ...(owner ? { owner } : {}),\n ...(repositoryName ? { name: repositoryName } : {}),\n };\n}\n\nconst resolveRepositoryIdentityCacheKey = Effect.fn(\"RepositoryIdentityResolver.resolveCacheKey\")(\n function* (cwd: string) {\n const processRunner = yield* ProcessRunner.ProcessRunner;\n let cacheKey = cwd;\n\n // git is a real executable on every platform — no cmd.exe shell mode, which\n // would split paths containing spaces during cmd's re-tokenization.\n const topLevelResult = yield* processRunner\n .run({\n command: \"git\",\n args: [\"-C\", cwd, \"rev-parse\", \"--show-toplevel\"],\n timeoutBehavior: \"timedOutResult\",\n })\n .pipe(Effect.option);\n if (topLevelResult._tag === \"None\" || topLevelResult.value.code !== 0) {\n return cacheKey;\n }\n\n const candidate = topLevelResult.value.stdout.trim();\n if (candidate.length > 0) {\n cacheKey = candidate;\n }\n\n return cacheKey;\n },\n);\n\nconst resolveRepositoryIdentityFromCacheKey = Effect.fn(\n \"RepositoryIdentityResolver.resolveFromCacheKey\",\n)(function* (\n cacheKey: string,\n): Effect.fn.Return {\n const processRunner = yield* ProcessRunner.ProcessRunner;\n const remoteResult = yield* processRunner\n .run({\n command: \"git\",\n args: [\"-C\", cacheKey, \"remote\", \"-v\"],\n timeoutBehavior: \"timedOutResult\",\n })\n .pipe(Effect.option);\n if (remoteResult._tag === \"None\" || remoteResult.value.code !== 0) {\n return null;\n }\n\n const remote = pickPrimaryRemote(parseRemoteFetchUrls(remoteResult.value.stdout));\n return remote ? buildRepositoryIdentity({ ...remote, rootPath: cacheKey }) : null;\n});\n\nexport const make = Effect.fn(\"RepositoryIdentityResolver.make\")(function* (\n options: RepositoryIdentityResolverOptions = {},\n) {\n const processRunner = yield* ProcessRunner.ProcessRunner;\n\n const repositoryIdentityCache = yield* Cache.makeWith(\n (cacheKey) =>\n resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(\n Effect.provideService(ProcessRunner.ProcessRunner, processRunner),\n ),\n {\n capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,\n timeToLive: Exit.match({\n onSuccess: (value) =>\n value === null\n ? (options.negativeCacheTtl ?? DEFAULT_NEGATIVE_CACHE_TTL)\n : (options.positiveCacheTtl ?? DEFAULT_POSITIVE_CACHE_TTL),\n onFailure: () => Duration.zero,\n }),\n },\n );\n\n const resolve: RepositoryIdentityResolver[\"Service\"][\"resolve\"] = Effect.fn(\n \"RepositoryIdentityResolver.resolve\",\n )(function* (cwd) {\n const cacheKey = yield* resolveRepositoryIdentityCacheKey(cwd).pipe(\n Effect.provideService(ProcessRunner.ProcessRunner, processRunner),\n );\n return yield* Cache.get(repositoryIdentityCache, cacheKey);", + "checksum": "4a4f8be0eeff3ff2856b99be1dc3e109597f73ef9dfb6c89fb54aef34a4f6fff" + }, + "project-identity-read-projection": { + "id": "project-identity-read-projection", + "path": "apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts", + "start": 313, + "end": 388, + "language": "typescript", + "label": "Snapshot-time repository identity enrichment", + "code": "function mapProjectShellRow(\n row: Schema.Schema.Type,\n repositoryIdentity: OrchestrationProject[\"repositoryIdentity\"],\n): OrchestrationProjectShell {\n return {\n id: row.projectId,\n title: row.title,\n workspaceRoot: row.workspaceRoot,\n repositoryIdentity,\n defaultModelSelection: row.defaultModelSelection,\n defaultThreadEnvMode: row.defaultThreadEnvMode,\n faviconPath: row.faviconPath ?? null,\n scripts: row.scripts,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction mapProposedPlanRow(\n row: Schema.Schema.Type,\n): OrchestrationProposedPlan {\n return {\n id: row.planId,\n turnId: row.turnId,\n planMarkdown: row.planMarkdown,\n implementedAt: row.implementedAt,\n implementationThreadId: row.implementationThreadId,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toPersistenceSqlOrDecodeError(sqlOperation: string, decodeOperation: string) {\n return (cause: unknown): ProjectionRepositoryError =>\n Schema.isSchemaError(cause)\n ? toPersistenceDecodeError(decodeOperation)(cause)\n : toPersistenceSqlError(sqlOperation)(cause);\n}\n\nconst makeProjectionSnapshotQuery = Effect.gen(function* () {\n const threadBackgroundLiveness = yield* ThreadBackgroundLivenessService;\n const threadPlanProgress = yield* ThreadPlanProgressService;\n const sql = yield* SqlClient.SqlClient;\n const repositoryIdentityResolver = yield* RepositoryIdentityResolver.RepositoryIdentityResolver;\n const repositoryIdentityResolutionConcurrency = 4;\n const resolveRepositoryIdentitiesForProjects = Effect.fn(\n \"ProjectionSnapshotQuery.resolveRepositoryIdentitiesForProjects\",\n )(function* (\n projectRows: ReadonlyArray>,\n options?: {\n readonly includeDeleted?: boolean;\n },\n ) {\n const filteredProjectRows =\n options?.includeDeleted === true\n ? projectRows\n : projectRows.filter((row) => row.deletedAt === null);\n const uniqueWorkspaceRoots = [...new Set(filteredProjectRows.map((row) => row.workspaceRoot))];\n const repositoryIdentityByWorkspaceRoot = new Map(\n yield* Effect.forEach(\n uniqueWorkspaceRoots,\n (workspaceRoot) =>\n repositoryIdentityResolver\n .resolve(workspaceRoot)\n .pipe(Effect.map((identity) => [workspaceRoot, identity] as const)),\n { concurrency: repositoryIdentityResolutionConcurrency },\n ),\n );\n\n return new Map(\n filteredProjectRows.map((row) => [\n row.projectId,\n repositoryIdentityByWorkspaceRoot.get(row.workspaceRoot) ?? null,\n ]),\n );\n });", + "checksum": "7d141cd37e227fc76fc88c9537c8bb8dd65842f91b9e2ec7fdec540a2913c122" + }, + "project-durable-projection": { + "id": "project-durable-projection", + "path": "apps/server/src/orchestration/decider.ts", + "start": 227, + "end": 298, + "language": "typescript", + "label": "Project creation and metadata event decisions", + "code": " case \"project.create\": {\n yield* requireProjectAbsent({\n readModel,\n command,\n projectId: command.projectId,\n });\n yield* requireActiveProjectWorkspaceRootAbsent({\n readModel,\n command,\n workspaceRoot: command.workspaceRoot,\n exceptProjectId: command.projectId,\n });\n\n return {\n ...(yield* withEventBase({\n aggregateKind: \"project\",\n aggregateId: command.projectId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"project.created\",\n payload: {\n projectId: command.projectId,\n title: command.title,\n workspaceRoot: command.workspaceRoot,\n defaultModelSelection: command.defaultModelSelection ?? null,\n faviconPath: null,\n scripts: [],\n createdAt: command.createdAt,\n updatedAt: command.createdAt,\n },\n };\n }\n\n case \"project.meta.update\": {\n yield* requireProject({\n readModel,\n command,\n projectId: command.projectId,\n });\n if (command.workspaceRoot !== undefined) {\n yield* requireActiveProjectWorkspaceRootAbsent({\n readModel,\n command,\n workspaceRoot: command.workspaceRoot,\n exceptProjectId: command.projectId,\n });\n }\n const occurredAt = yield* nowIso;\n return {\n ...(yield* withEventBase({\n aggregateKind: \"project\",\n aggregateId: command.projectId,\n occurredAt,\n commandId: command.commandId,\n })),\n type: \"project.meta-updated\",\n payload: {\n projectId: command.projectId,\n ...(command.title !== undefined ? { title: command.title } : {}),\n ...(command.workspaceRoot !== undefined ? { workspaceRoot: command.workspaceRoot } : {}),\n ...(command.defaultModelSelection !== undefined\n ? { defaultModelSelection: command.defaultModelSelection }\n : {}),\n ...(command.defaultThreadEnvMode !== undefined\n ? { defaultThreadEnvMode: command.defaultThreadEnvMode }\n : {}),\n ...(command.faviconPath !== undefined ? { faviconPath: command.faviconPath } : {}),\n ...(command.scripts !== undefined ? { scripts: command.scripts } : {}),\n updatedAt: occurredAt,\n },\n };", + "checksum": "e788184b10630834970883f5f18d9c6b555e7ecc2993eaedf944acaf4afddf0b" + }, + "project-projector": { + "id": "project-projector", + "path": "apps/server/src/orchestration/projector.ts", + "start": 207, + "end": 263, + "language": "typescript", + "label": "Durable project read-model projection", + "code": " switch (event.type) {\n case \"project.created\":\n return decodeForEvent(ProjectCreatedPayload, event.payload, event.type, \"payload\").pipe(\n Effect.map((payload) => {\n const existing = nextBase.projects.find((entry) => entry.id === payload.projectId);\n const nextProject = {\n id: payload.projectId,\n title: payload.title,\n workspaceRoot: payload.workspaceRoot,\n defaultModelSelection: payload.defaultModelSelection,\n defaultThreadEnvMode: null,\n faviconPath: payload.faviconPath ?? null,\n scripts: payload.scripts,\n createdAt: payload.createdAt,\n updatedAt: payload.updatedAt,\n deletedAt: null,\n };\n\n return {\n ...nextBase,\n projects: existing\n ? nextBase.projects.map((entry) =>\n entry.id === payload.projectId ? nextProject : entry,\n )\n : [...nextBase.projects, nextProject],\n };\n }),\n );\n\n case \"project.meta-updated\":\n return decodeForEvent(ProjectMetaUpdatedPayload, event.payload, event.type, \"payload\").pipe(\n Effect.map((payload) => ({\n ...nextBase,\n projects: nextBase.projects.map((project) =>\n project.id === payload.projectId\n ? {\n ...project,\n ...(payload.title !== undefined ? { title: payload.title } : {}),\n ...(payload.workspaceRoot !== undefined\n ? { workspaceRoot: payload.workspaceRoot }\n : {}),\n ...(payload.defaultModelSelection !== undefined\n ? { defaultModelSelection: payload.defaultModelSelection }\n : {}),\n ...(payload.defaultThreadEnvMode !== undefined\n ? { defaultThreadEnvMode: payload.defaultThreadEnvMode }\n : {}),\n ...(payload.faviconPath !== undefined\n ? { faviconPath: payload.faviconPath }\n : {}),\n ...(payload.scripts !== undefined ? { scripts: payload.scripts } : {}),\n updatedAt: payload.updatedAt,\n }\n : project,\n ),\n })),\n );", + "checksum": "729a2f33d9502369b95c9f126893ba31605baac1c1ae7f5ecfabadb71399f48e" + }, + "project-logical-grouping": { + "id": "project-logical-grouping", + "path": "packages/client-runtime/src/state/projectGrouping.ts", + "start": 67, + "end": 140, + "language": "typescript", + "label": "Client-side physical and logical project grouping", + "code": "export function derivePhysicalProjectKeyFromPath(environmentId: string, cwd: string): string {\n return `${environmentId}:${normalizeProjectPathForComparison(cwd)}`;\n}\n\nexport function derivePhysicalProjectKey(\n project: Pick,\n): string {\n return derivePhysicalProjectKeyFromPath(project.environmentId, project.workspaceRoot);\n}\n\nexport function deriveProjectGroupingOverrideKey(\n project: Pick,\n): string {\n return derivePhysicalProjectKey(project);\n}\n\nexport function getProjectOrderKey(\n project: Pick,\n): string {\n return derivePhysicalProjectKey(project);\n}\n\nexport function resolveProjectGroupingMode(\n project: Pick,\n settings: ProjectGroupingSettings,\n): SidebarProjectGroupingMode {\n return (\n settings.sidebarProjectGroupingOverrides?.[deriveProjectGroupingOverrideKey(project)] ??\n settings.sidebarProjectGroupingMode\n );\n}\n\nfunction deriveRepositoryScopedKey(\n project: Pick,\n groupingMode: SidebarProjectGroupingMode,\n): string | null {\n const canonicalKey = project.repositoryIdentity?.canonicalKey;\n if (!canonicalKey) {\n return null;\n }\n\n if (groupingMode === \"repository\") {\n return canonicalKey;\n }\n\n const relativeProjectPath = deriveRepositoryRelativeProjectPath(project);\n if (relativeProjectPath === null) {\n return canonicalKey;\n }\n\n return relativeProjectPath.length === 0\n ? canonicalKey\n : `${canonicalKey}::${relativeProjectPath}`;\n}\n\nexport function deriveLogicalProjectKey(\n project: Pick<\n EnvironmentProject,\n \"environmentId\" | \"id\" | \"workspaceRoot\" | \"repositoryIdentity\"\n >,\n options?: {\n readonly groupingMode?: SidebarProjectGroupingMode;\n },\n): string {\n const groupingMode = options?.groupingMode ?? \"repository\";\n if (groupingMode === \"separate\") {\n return derivePhysicalProjectKey(project);\n }\n\n return (\n deriveRepositoryScopedKey(project, groupingMode) ??\n derivePhysicalProjectKey(project) ??\n scopedProjectKey(scopeProjectRef(project.environmentId, project.id))\n );", + "checksum": "5dba3332ba0509524b5efd5bf70acdb14f099330583ae7878ae53a7bde32ed95" + }, + "project-environment-label": { + "id": "project-environment-label", + "path": "apps/web/src/sidebarProjectGrouping.ts", + "start": 53, + "end": 115, + "language": "typescript", + "label": "Environment labels retained in grouped sidebar projects", + "code": "export function buildSidebarProjectSnapshots(input: {\n projects: ReadonlyArray;\n settings: ProjectGroupingSettings;\n primaryEnvironmentId: EnvironmentId | null;\n resolveEnvironmentLabel: (environmentId: EnvironmentId) => string | null;\n // Returns true when an env id maps to a desktopLocal saved-env\n // record (today: the WSL backend). Defaults to \"false for every\n // env\" so callers that don't care about the distinction get the\n // legacy behavior.\n isDesktopLocalEnvironment?: (environmentId: EnvironmentId) => boolean;\n}): SidebarProjectSnapshot[] {\n return buildProjectGroups({\n projects: input.projects,\n settings: input.settings,\n preferredEnvironmentId: input.primaryEnvironmentId,\n }).map((group): SidebarProjectSnapshot => {\n const members = group.members.map(\n ({ physicalProjectKey, project }): SidebarProjectGroupMember => ({\n ...project,\n physicalProjectKey,\n environmentLabel: input.resolveEnvironmentLabel(project.environmentId),\n }),\n );\n const representative =\n members.find(\n (member) =>\n member.environmentId === group.representative.environmentId &&\n member.id === group.representative.id,\n ) ?? members[0]!;\n\n const hasLocal =\n input.primaryEnvironmentId !== null &&\n members.some((member) => member.environmentId === input.primaryEnvironmentId);\n const hasRemote =\n input.primaryEnvironmentId !== null\n ? members.some((member) => member.environmentId !== input.primaryEnvironmentId)\n : false;\n const remoteMembers = members.filter(\n (member) =>\n input.primaryEnvironmentId !== null && member.environmentId !== input.primaryEnvironmentId,\n );\n const remoteEnvironmentLabels = remoteMembers\n .flatMap((member) => (member.environmentLabel ? [member.environmentLabel] : []))\n .filter((label, index, labels) => labels.indexOf(label) === index);\n const isDesktopLocal = input.isDesktopLocalEnvironment ?? (() => false);\n const allRemoteMembersAreDesktopLocal =\n remoteMembers.length > 0 &&\n remoteMembers.every((member) => isDesktopLocal(member.environmentId));\n\n return {\n ...representative,\n projectKey: group.key,\n displayName: group.label,\n groupedProjectCount: members.length,\n environmentPresence:\n hasLocal && hasRemote ? \"mixed\" : hasRemote ? \"remote-only\" : \"local-only\",\n allRemoteMembersAreDesktopLocal,\n memberProjects: members,\n memberProjectRefs: group.memberProjectRefs,\n remoteEnvironmentLabels,\n };\n });\n}", + "checksum": "991d462dd85ddad3333fca1606c7beac65a41aa4b90282ba4794991ef9e2fb6e" + }, + "project-setup-script-selection": { + "id": "project-setup-script-selection", + "path": "packages/shared/src/projectScripts.ts", + "start": 11, + "end": 37, + "language": "typescript", + "label": "Worktree setup-script selection and environment construction", + "code": "export function projectScriptCwd(input: {\n project: {\n cwd: string;\n };\n worktreePath?: string | null;\n}): string {\n return input.worktreePath ?? input.project.cwd;\n}\n\nexport function projectScriptRuntimeEnv(\n input: ProjectScriptRuntimeEnvInput,\n): Record {\n const env: Record = {\n T3CODE_PROJECT_ROOT: input.project.cwd,\n };\n if (input.worktreePath) {\n env.T3CODE_WORKTREE_PATH = input.worktreePath;\n }\n if (input.extraEnv) {\n return { ...env, ...input.extraEnv };\n }\n return env;\n}\n\nexport function setupProjectScript(scripts: readonly ProjectScript[]): ProjectScript | null {\n return scripts.find((script) => script.runOnWorktreeCreate) ?? null;\n}", + "checksum": "78e76784914a8a10cc610f1b31943af278b003d98790ddffe5243b8ddeb8f7d8" + }, + "project-setup-script-runner": { + "id": "project-setup-script-runner", + "path": "apps/server/src/project/ProjectSetupScriptRunner.ts", + "start": 123, + "end": 183, + "language": "typescript", + "label": "Setup script launched in the linked worktree terminal", + "code": " if (!project) {\n return yield* new ProjectSetupScriptProjectNotFoundError(errorContext);\n }\n\n const script = setupProjectScript(project.scripts);\n if (!script) {\n return {\n status: \"no-script\",\n } as const;\n }\n\n const terminalId = input.preferredTerminalId ?? `setup-${script.id}`;\n const cwd = input.worktreePath;\n const env = projectScriptRuntimeEnv({\n project: { cwd: project.workspaceRoot },\n worktreePath: input.worktreePath,\n });\n\n yield* terminalManager\n .open({\n threadId: input.threadId,\n terminalId,\n cwd,\n worktreePath: input.worktreePath,\n env,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ProjectSetupScriptOperationError({\n ...errorContext,\n operation: \"openTerminal\",\n cause,\n }),\n ),\n );\n yield* terminalManager\n .write({\n threadId: input.threadId,\n terminalId,\n data: `${script.command}\\r`,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ProjectSetupScriptOperationError({\n ...errorContext,\n operation: \"writeCommand\",\n cause,\n }),\n ),\n );\n\n return {\n status: \"started\",\n scriptId: script.id,\n scriptName: script.name,\n terminalId,\n cwd,\n } as const;\n });", + "checksum": "cff81f3c6730404adcbbfda69be3407b3d365eda8730a8f780e36b80a0fe2395" + }, + "worktree-non-git-fallback": { + "id": "worktree-non-git-fallback", + "path": "apps/web/src/components/ChatView.logic.ts", + "start": 322, + "end": 327, + "language": "typescript", + "label": "Non-Git projects fall back from worktree to local mode", + "code": "export function resolveSendEnvMode(input: {\n requestedEnvMode: DraftThreadEnvMode;\n isGitRepo: boolean;\n}): DraftThreadEnvMode {\n return input.isGitRepo ? input.requestedEnvMode : \"local\";\n}", + "checksum": "f7e6d7316e8bb7115262ee669771235b851a046fb5943c03ae99edc63a2d8cbd" + }, + "worktree-ref-occupancy": { + "id": "worktree-ref-occupancy", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2463, + "end": 2559, + "language": "typescript", + "label": "Git worktree listing decorates occupied branch references", + "code": " const readGitRefsSnapshot = Effect.fn(\"readGitRefsSnapshot\")(function* (gitCommonDir: string) {\n const fetchCwd =\n path.basename(gitCommonDir) === \".git\" ? path.dirname(gitCommonDir) : gitCommonDir;\n const gitDirArgs = [\"--git-dir\", gitCommonDir] as const;\n const [refsResult, defaultRefResult, worktreeListResult, remoteNamesResult] = yield* Effect.all(\n [\n executeGitWithStableDiagnostics(\n \"GitVcsDriver.listRefs.snapshotRefs\",\n fetchCwd,\n [\n ...gitDirArgs,\n \"for-each-ref\",\n \"--format=%(refname)%09%(committerdate:unix)%09%(symref)\",\n \"refs/heads\",\n \"refs/remotes\",\n ],\n {\n timeoutMs: 30_000,\n maxOutputBytes: 16 * 1024 * 1024,\n fallbackErrorDetail: \"Git ref snapshot enumeration failed.\",\n },\n ),\n executeGit(\n \"GitVcsDriver.listRefs.defaultRef\",\n fetchCwd,\n [...gitDirArgs, \"symbolic-ref\", \"refs/remotes/origin/HEAD\"],\n {\n timeoutMs: 5_000,\n allowNonZeroExit: true,\n },\n ),\n executeGit(\n \"GitVcsDriver.listRefs.worktreeList\",\n fetchCwd,\n [...gitDirArgs, \"worktree\", \"list\", \"--porcelain\", \"-z\"],\n {\n timeoutMs: 30_000,\n allowNonZeroExit: true,\n maxOutputBytes: 16 * 1024 * 1024,\n },\n ),\n executeGit(\"GitVcsDriver.listRefs.remoteNames\", fetchCwd, [...gitDirArgs, \"remote\"], {\n timeoutMs: 5_000,\n allowNonZeroExit: true,\n }),\n ],\n { concurrency: 2 },\n );\n\n const remoteNames =\n remoteNamesResult.exitCode === 0 ? parseRemoteNames(remoteNamesResult.stdout) : [];\n if (remoteNamesResult.exitCode !== 0 && remoteNamesResult.stderr.trim().length > 0) {\n yield* Effect.logWarning(\n `GitVcsDriver.listRefs: remote name lookup returned code ${remoteNamesResult.exitCode} for ${gitCommonDir}: ${remoteNamesResult.stderr.trim()}. Falling back to an empty remote name list.`,\n );\n }\n const defaultBranch =\n defaultRefResult.exitCode === 0\n ? defaultRefResult.stdout.trim().replace(/^refs\\/remotes\\/origin\\//, \"\")\n : null;\n const parsedWorktreeEntries =\n worktreeListResult.exitCode === 0\n ? [...parseWorktreeBranchPaths(worktreeListResult.stdout)].map(\n ([branchName, worktreePath]) =>\n [branchName, path.normalize(path.resolve(worktreePath))] as const,\n )\n : [];\n const existingWorktreeEntries = yield* Effect.filter(\n parsedWorktreeEntries,\n ([, worktreePath]) =>\n fileSystem.stat(worktreePath).pipe(\n Effect.as(true),\n Effect.orElseSucceed(() => false),\n ),\n { concurrency: 16 },\n );\n const worktreeMap = new Map(existingWorktreeEntries);\n const localBranches: Array<{ readonly ref: VcsRef; readonly lastCommit: number }> = [];\n const remoteBranches: Array<{ readonly ref: VcsRef; readonly lastCommit: number }> = [];\n\n for (const line of refsResult.stdout.split(\"\\n\")) {\n if (line.length === 0) continue;\n const [fullRefName, lastCommitRaw, symbolicTarget] = line.split(\"\\t\");\n if (!fullRefName || symbolicTarget) continue;\n const parsedLastCommit = Number.parseInt(lastCommitRaw ?? \"0\", 10);\n const lastCommit = Number.isFinite(parsedLastCommit) ? parsedLastCommit : 0;\n\n if (fullRefName.startsWith(\"refs/heads/\")) {\n const name = fullRefName.slice(\"refs/heads/\".length);\n localBranches.push({\n ref: {\n name,\n current: false,\n isRemote: false,\n isDefault: name === defaultBranch,\n worktreePath: worktreeMap.get(name) ?? null,\n },", + "checksum": "0d568abc710d939aac21b967910cb9bd479b61ebd13ad26bcbc87c919cac7743" + }, + "worktree-create-remove-contract": { + "id": "worktree-create-remove-contract", + "path": "packages/contracts/src/git.ts", + "start": 124, + "end": 165, + "language": "typescript", + "label": "Worktree creation and removal RPC inputs", + "code": "export const VcsListRefsInput = Schema.Struct({\n cwd: TrimmedNonEmptyStringSchema,\n query: Schema.optional(TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(256))),\n cursor: Schema.optional(NonNegativeInt),\n includeMatchingRemoteRefs: Schema.optional(Schema.Boolean),\n refKind: Schema.optional(Schema.Literals([\"all\", \"local\", \"remote\"])),\n refresh: Schema.optional(Schema.Boolean),\n limit: Schema.optional(\n PositiveInt.check(Schema.isLessThanOrEqualTo(GIT_LIST_BRANCHES_MAX_LIMIT)),\n ),\n});\nexport type VcsListRefsInput = typeof VcsListRefsInput.Type;\n\nexport const VcsCreateWorktreeInput = Schema.Struct({\n cwd: TrimmedNonEmptyStringSchema,\n refName: TrimmedNonEmptyStringSchema,\n newRefName: Schema.optional(TrimmedNonEmptyStringSchema),\n baseRefName: Schema.optional(TrimmedNonEmptyStringSchema),\n path: Schema.NullOr(TrimmedNonEmptyStringSchema),\n});\nexport type VcsCreateWorktreeInput = typeof VcsCreateWorktreeInput.Type;\n\nexport const GitPullRequestRefInput = Schema.Struct({\n cwd: TrimmedNonEmptyStringSchema,\n reference: GitPullRequestReference,\n});\nexport type GitPullRequestRefInput = typeof GitPullRequestRefInput.Type;\n\nexport const GitPreparePullRequestThreadInput = Schema.Struct({\n cwd: TrimmedNonEmptyStringSchema,\n reference: GitPullRequestReference,\n mode: GitPreparePullRequestThreadMode,\n threadId: Schema.optional(ThreadId),\n});\nexport type GitPreparePullRequestThreadInput = typeof GitPreparePullRequestThreadInput.Type;\n\nexport const VcsRemoveWorktreeInput = Schema.Struct({\n cwd: TrimmedNonEmptyStringSchema,\n path: TrimmedNonEmptyStringSchema,\n force: Schema.optional(Schema.Boolean),\n});\nexport type VcsRemoveWorktreeInput = typeof VcsRemoveWorktreeInput.Type;", + "checksum": "38f837fcc1bd73ea692ff819c248771f4eba476d0336357698d09ffdfa20bad2" + }, + "worktree-result-contract": { + "id": "worktree-result-contract", + "path": "packages/contracts/src/git.ts", + "start": 264, + "end": 294, + "language": "typescript", + "label": "Worktree and pull-request preparation results", + "code": "export const VcsListRefsResult = Schema.Struct({\n refs: Schema.Array(VcsRef),\n isRepo: Schema.Boolean,\n hasPrimaryRemote: Schema.Boolean,\n nextCursor: NonNegativeInt.pipe(Schema.NullOr),\n totalCount: NonNegativeInt,\n});\nexport type VcsListRefsResult = typeof VcsListRefsResult.Type;\n\nexport const VcsCreateWorktreeResult = Schema.Struct({\n worktree: VcsWorktree,\n});\nexport type VcsCreateWorktreeResult = typeof VcsCreateWorktreeResult.Type;\n\nexport const GitResolvePullRequestResult = Schema.Struct({\n pullRequest: GitResolvedPullRequest,\n});\nexport type GitResolvePullRequestResult = typeof GitResolvePullRequestResult.Type;\n\nexport const GitPreparePullRequestThreadResult = Schema.Struct({\n pullRequest: GitResolvedPullRequest,\n branch: TrimmedNonEmptyStringSchema,\n worktreePath: TrimmedNonEmptyStringSchema.pipe(Schema.NullOr),\n /**\n * False when the checkout could not be brought to the pull request head — a reused worktree\n * holding local commits or uncommitted changes keeps its own state, so the code being handed\n * over is older than the pull request.\n */\n isOnPullRequestHead: Schema.Boolean,\n});\nexport type GitPreparePullRequestThreadResult = typeof GitPreparePullRequestThreadResult.Type;", + "checksum": "be9e1709dcb7b1c171e5a679852c15f2b5e16949f1bde705f05f5d01086a63ee" + }, + "worktree-bootstrap-path": { + "id": "worktree-bootstrap-path", + "path": "apps/server/src/ws.ts", + "start": 979, + "end": 1022, + "language": "typescript", + "label": "Origin-aware worktree bootstrap saga", + "code": " if (bootstrap?.prepareWorktree) {\n let worktreeBaseRef = bootstrap.prepareWorktree.baseBranch;\n // \"Start from origin\" is a stored default; repos without an\n // origin remote fall back to the local base branch instead of\n // failing the whole bootstrap on `git fetch origin`.\n const startFromOrigin =\n bootstrap.prepareWorktree.startFromOrigin === true &&\n (yield* gitWorkflow.remoteExists({\n cwd: bootstrap.prepareWorktree.projectCwd,\n remoteName: \"origin\",\n }));\n if (startFromOrigin) {\n yield* gitWorkflow.fetchRemote({\n cwd: bootstrap.prepareWorktree.projectCwd,\n remoteName: \"origin\",\n });\n const resolvedRemoteBase = yield* gitWorkflow.resolveRemoteTrackingCommit({\n cwd: bootstrap.prepareWorktree.projectCwd,\n refName: bootstrap.prepareWorktree.baseBranch,\n fallbackRemoteName: \"origin\",\n });\n worktreeBaseRef = resolvedRemoteBase.commitSha;\n }\n const worktree = yield* gitWorkflow.createWorktree({\n cwd: bootstrap.prepareWorktree.projectCwd,\n refName: worktreeBaseRef,\n newRefName: bootstrap.prepareWorktree.branch,\n baseRefName: bootstrap.prepareWorktree.baseBranch,\n path: null,\n });\n targetWorktreePath = worktree.worktree.path;\n yield* dispatchFromClient({\n type: \"thread.meta.update\",\n commandId: yield* serverCommandId(\"bootstrap-thread-meta-update\"),\n threadId: command.threadId,\n branch: worktree.worktree.refName,\n worktreePath: targetWorktreePath,\n });\n yield* refreshGitStatus(targetWorktreePath);\n }\n\n yield* runSetupProgram();\n\n return yield* dispatchFromClient(finalTurnStartCommand);", + "checksum": "d243bf017c0fece3cfeca6fcec59f80633bae6e4358beecd85c6afdff52e31c1" + }, + "worktree-origin-base-test": { + "id": "worktree-origin-base-test", + "path": "apps/server/src/vcs/GitVcsDriverCore.test.ts", + "start": 1505, + "end": 1565, + "language": "typescript", + "label": "Remote base reference worktree creation test", + "code": " it.effect(\"creates a worktree from the latest fetched remote commit\", () =>\n Effect.gen(function* () {\n const cwd = yield* makeTmpDir();\n const remote = yield* makeTmpDir(\"git-remote-\");\n const peer = yield* makeTmpDir(\"git-peer-\");\n const { initialBranch } = yield* initRepoWithCommit(cwd);\n yield* git(remote, [\"init\", \"--bare\"]);\n yield* git(cwd, [\"remote\", \"add\", \"origin\", remote]);\n yield* git(cwd, [\"push\", \"-u\", \"origin\", initialBranch]);\n yield* git(remote, [\"symbolic-ref\", \"HEAD\", `refs/heads/${initialBranch}`]);\n const beforeFetch = yield* git(cwd, [\"rev-parse\", `refs/remotes/origin/${initialBranch}`]);\n\n yield* git(peer, [\"clone\", remote, \".\"]);\n yield* git(peer, [\"config\", \"user.email\", \"test@test.com\"]);\n yield* git(peer, [\"config\", \"user.name\", \"Test\"]);\n yield* writeTextFile(peer, \"remote-change.txt\", \"remote\\n\");\n yield* git(peer, [\"add\", \"remote-change.txt\"]);\n yield* git(peer, [\"commit\", \"-m\", \"remote change\"]);\n yield* git(peer, [\"push\", \"origin\", initialBranch]);\n const remoteHead = yield* git(peer, [\"rev-parse\", \"HEAD\"]);\n assert.notEqual(beforeFetch, remoteHead);\n\n const driver = yield* GitVcsDriver.GitVcsDriver;\n yield* driver.fetchRemote({ cwd, remoteName: \"origin\" });\n\n const resolvedBase = yield* driver.resolveRemoteTrackingCommit({\n cwd,\n refName: initialBranch,\n fallbackRemoteName: \"origin\",\n });\n const explicitlyResolvedBase = yield* driver.resolveRemoteTrackingCommit({\n cwd,\n refName: `origin/${initialBranch}`,\n fallbackRemoteName: \"origin\",\n });\n\n assert.deepEqual(resolvedBase, {\n commitSha: remoteHead,\n remoteRefName: `origin/${initialBranch}`,\n });\n assert.deepEqual(explicitlyResolvedBase, resolvedBase);\n assert.equal(yield* git(cwd, [\"rev-parse\", initialBranch]), beforeFetch);\n\n const pathService = yield* Path.Path;\n const worktreePath = pathService.join(\n yield* makeTmpDir(\"git-fetched-worktrees-\"),\n \"fetched-origin\",\n );\n yield* driver.createWorktree({\n cwd,\n path: worktreePath,\n refName: resolvedBase.commitSha,\n newRefName: \"t3code/fetched-origin\",\n baseRefName: resolvedBase.remoteRefName,\n });\n\n assert.equal(yield* git(worktreePath, [\"rev-parse\", \"HEAD\"]), remoteHead);\n assert.equal(\n yield* driver.readConfigValue(worktreePath, \"branch.t3code/fetched-origin.gh-merge-base\"),\n initialBranch,\n );", + "checksum": "3079485524aec02260b358299da023b6dda92f6b257cd7abe203530cca242022" + }, + "worktree-create-command": { + "id": "worktree-create-command", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2763, + "end": 2799, + "language": "typescript", + "label": "Git worktree add command and default linked path", + "code": " const createWorktree: GitVcsDriver.GitVcsDriver[\"Service\"][\"createWorktree\"] = Effect.fn(\n \"createWorktree\",\n )(function* (input) {\n const targetBranch = input.newRefName ?? input.refName;\n const sanitizedBranch = targetBranch.replace(/\\//g, \"-\");\n const repoName = path.basename(input.cwd);\n const worktreePath = input.path ?? path.join(worktreesDir, repoName, sanitizedBranch);\n const args = input.newRefName\n ? [\"worktree\", \"add\", \"-b\", input.newRefName, worktreePath, input.refName]\n : [\"worktree\", \"add\", worktreePath, input.refName];\n\n yield* executeGit(\"GitVcsDriver.createWorktree\", input.cwd, args, {\n fallbackErrorDetail: \"git worktree add failed\",\n timeoutMs: WORKTREE_ADD_TIMEOUT_MS,\n });\n\n if (input.newRefName && input.baseRefName) {\n const remoteNames = yield* listRemoteNames(input.cwd).pipe(Effect.orElseSucceed(() => []));\n const parsedBaseRef = parseRemoteRefWithRemoteNames(\n input.baseRefName,\n remoteNames.toSorted((left, right) => right.length - left.length),\n );\n const baseBranch = parsedBaseRef?.branchName ?? input.baseRefName;\n yield* runGit(\"GitVcsDriver.createWorktree.configureBaseRef\", input.cwd, [\n \"config\",\n `branch.${input.newRefName}.gh-merge-base`,\n baseBranch,\n ]);\n }\n\n return {\n worktree: {\n path: worktreePath,\n refName: targetBranch,\n },\n };\n });", + "checksum": "4c15353dd8e82554c229e870a3625673d90574db5b6c7ae4396b332f837f61c3" + }, + "worktree-setup-runner": { + "id": "worktree-setup-runner", + "path": "apps/server/src/project/ProjectSetupScriptRunner.ts", + "start": 123, + "end": 183, + "language": "typescript", + "label": "Post-creation setup script runner", + "code": " if (!project) {\n return yield* new ProjectSetupScriptProjectNotFoundError(errorContext);\n }\n\n const script = setupProjectScript(project.scripts);\n if (!script) {\n return {\n status: \"no-script\",\n } as const;\n }\n\n const terminalId = input.preferredTerminalId ?? `setup-${script.id}`;\n const cwd = input.worktreePath;\n const env = projectScriptRuntimeEnv({\n project: { cwd: project.workspaceRoot },\n worktreePath: input.worktreePath,\n });\n\n yield* terminalManager\n .open({\n threadId: input.threadId,\n terminalId,\n cwd,\n worktreePath: input.worktreePath,\n env,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ProjectSetupScriptOperationError({\n ...errorContext,\n operation: \"openTerminal\",\n cause,\n }),\n ),\n );\n yield* terminalManager\n .write({\n threadId: input.threadId,\n terminalId,\n data: `${script.command}\\r`,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ProjectSetupScriptOperationError({\n ...errorContext,\n operation: \"writeCommand\",\n cause,\n }),\n ),\n );\n\n return {\n status: \"started\",\n scriptId: script.id,\n scriptName: script.name,\n terminalId,\n cwd,\n } as const;\n });", + "checksum": "cff81f3c6730404adcbbfda69be3407b3d365eda8730a8f780e36b80a0fe2395" + }, + "worktree-setup-test": { + "id": "worktree-setup-test", + "path": "apps/server/src/project/ProjectSetupScriptRunner.test.ts", + "start": 93, + "end": 152, + "language": "typescript", + "label": "Setup terminal cwd and environment test", + "code": " it.effect(\n \"opens the deterministic setup terminal with worktree env and writes the command\",\n () => {\n const open = vi.fn(() =>\n Effect.succeed({\n threadId: \"thread-1\",\n terminalId: \"setup-setup\",\n cwd: \"/repo/worktrees/a\",\n worktreePath: \"/repo/worktrees/a\",\n status: \"running\" as const,\n pid: 123,\n history: \"\",\n exitCode: null,\n exitSignal: null,\n label: \"setup-setup\",\n updatedAt: \"2026-01-01T00:00:00.000Z\",\n }),\n );\n const write = vi.fn(() => Effect.void);\n const project = makeProject([\n {\n id: \"setup\",\n name: \"Setup\",\n command: \"bun install\",\n icon: \"configure\",\n runOnWorktreeCreate: true,\n },\n ]);\n\n return Effect.gen(function* () {\n const runner = yield* ProjectSetupScriptRunner.ProjectSetupScriptRunner;\n const result = yield* runner.runForThread({\n threadId: \"thread-1\",\n projectCwd: \"/repo/project\",\n worktreePath: \"/repo/worktrees/a\",\n });\n\n expect(result).toEqual({\n status: \"started\",\n scriptId: \"setup\",\n scriptName: \"Setup\",\n terminalId: \"setup-setup\",\n cwd: \"/repo/worktrees/a\",\n });\n expect(open).toHaveBeenCalledWith({\n threadId: \"thread-1\",\n terminalId: \"setup-setup\",\n cwd: \"/repo/worktrees/a\",\n worktreePath: \"/repo/worktrees/a\",\n env: {\n T3CODE_PROJECT_ROOT: \"/repo/project\",\n T3CODE_WORKTREE_PATH: \"/repo/worktrees/a\",\n },\n });\n expect(write).toHaveBeenCalledWith({\n threadId: \"thread-1\",\n terminalId: \"setup-setup\",\n data: \"bun install\\r\",\n });\n }).pipe(Effect.provide(testLayer(project, { open, write })));", + "checksum": "97cc43e347199b1d18b1a9e4c57bc8933996c2e29b4db41a3d8b700fbf69ffaf" + }, + "worktree-remove-command": { + "id": "worktree-remove-command", + "path": "apps/server/src/vcs/GitVcsDriverCore.ts", + "start": 2982, + "end": 2994, + "language": "typescript", + "label": "Git worktree removal command", + "code": " const removeWorktree: GitVcsDriver.GitVcsDriver[\"Service\"][\"removeWorktree\"] = Effect.fn(\n \"removeWorktree\",\n )(function* (input) {\n const args = [\"worktree\", \"remove\"];\n if (input.force) {\n args.push(\"--force\");\n }\n args.push(input.path);\n yield* executeGit(\"GitVcsDriver.removeWorktree\", input.cwd, args, {\n timeoutMs: 15_000,\n fallbackErrorDetail: \"git worktree remove failed\",\n });\n });", + "checksum": "af8c3225d2530ef3532d7840a4f688233911c75f8750cb1287777d8a7b4dbf98" + }, + "worktree-create-remove-test": { + "id": "worktree-create-remove-test", + "path": "apps/server/src/vcs/GitVcsDriverCore.test.ts", + "start": 1377, + "end": 1403, + "language": "typescript", + "label": "Worktree create and remove integration test", + "code": " it.effect(\"creates and removes a worktree for a new refName\", () =>\n Effect.gen(function* () {\n const cwd = yield* makeTmpDir();\n const { initialBranch } = yield* initRepoWithCommit(cwd);\n const pathService = yield* Path.Path;\n const worktreePath = pathService.join(\n yield* makeTmpDir(\"git-worktrees-\"),\n \"feature-worktree\",\n );\n const driver = yield* GitVcsDriver.GitVcsDriver;\n\n const created = yield* driver.createWorktree({\n cwd,\n path: worktreePath,\n refName: initialBranch,\n newRefName: \"feature/worktree\",\n });\n\n assert.equal(created.worktree.path, worktreePath);\n assert.equal(created.worktree.refName, \"feature/worktree\");\n assert.equal(yield* git(worktreePath, [\"branch\", \"--show-current\"]), \"feature/worktree\");\n\n yield* driver.removeWorktree({ cwd, path: worktreePath });\n const fileSystem = yield* FileSystem.FileSystem;\n assert.equal(yield* fileSystem.exists(worktreePath), false);\n }),\n );", + "checksum": "7a00307d552baf90ff2b75e89cf5b2578a924b5f13fef6b4784fbf9f03a92160" + }, + "worktree-bootstrap-failure-cleanup": { + "id": "worktree-bootstrap-failure-cleanup", + "path": "apps/server/src/ws.ts", + "start": 1025, + "end": 1053, + "language": "typescript", + "label": "Bootstrap failure compensation for a newly created thread", + "code": " return yield* bootstrapProgram.pipe(\n Effect.catchCause((cause) => {\n const dispatchError = toBootstrapDispatchCommandCauseError(cause);\n if (Cause.hasInterruptsOnly(cause)) {\n return Effect.fail(dispatchError);\n }\n return Effect.uninterruptible(cleanupCreatedThread()).pipe(\n Effect.matchCauseEffect({\n onFailure: (cleanupCause) =>\n Effect.logWarning(\"bootstrap thread cleanup failed\", {\n threadId: command.threadId,\n detail: Cause.pretty(cleanupCause),\n }).pipe(Effect.flatMap(() => Effect.fail(dispatchError))),\n onSuccess: (threadDeleted) =>\n Effect.fail(\n threadDeleted\n ? new OrchestrationDispatchCommandError({\n message: dispatchError.message,\n ...(dispatchError.cause !== undefined\n ? { cause: dispatchError.cause }\n : {}),\n bootstrapThreadDisposition: \"deleted\",\n })\n : dispatchError,\n ),\n }),\n );\n }),\n );", + "checksum": "d2c16f4de66195ff88ab5b79da7e0944fd287f3bc58ca2743d12e972a780cd57" + }, + "turn-lifecycle-start-decider": { + "id": "turn-lifecycle-start-decider", + "path": "apps/server/src/orchestration/decider.ts", + "start": 926, + "end": 1036, + "language": "typescript", + "label": "Turn start intent and atomic lifecycle-reset event batch", + "code": " case \"thread.turn.start\": {\n const targetThread = yield* requireThread({\n readModel,\n command,\n threadId: command.threadId,\n });\n const sourceProposedPlan = command.sourceProposedPlan;\n const sourceThread = sourceProposedPlan\n ? yield* requireThread({\n readModel,\n command,\n threadId: sourceProposedPlan.threadId,\n })\n : null;\n const sourcePlan =\n sourceProposedPlan && sourceThread\n ? sourceThread.proposedPlans.find((entry) => entry.id === sourceProposedPlan.planId)\n : null;\n if (sourceProposedPlan && !sourcePlan) {\n return yield* new OrchestrationCommandInvariantError({\n commandType: command.type,\n detail: `Proposed plan '${sourceProposedPlan.planId}' does not exist on thread '${sourceProposedPlan.threadId}'.`,\n });\n }\n if (sourceThread && sourceThread.projectId !== targetThread.projectId) {\n return yield* new OrchestrationCommandInvariantError({\n commandType: command.type,\n detail: `Proposed plan '${sourceProposedPlan?.planId}' belongs to thread '${sourceThread.id}' in a different project.`,\n });\n }\n const userMessageEvent: Omit = {\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.message-sent\",\n payload: {\n threadId: command.threadId,\n messageId: command.message.messageId,\n role: \"user\",\n text: command.message.text,\n attachments: command.message.attachments,\n turnId: null,\n streaming: false,\n createdAt: command.createdAt,\n updatedAt: command.createdAt,\n },\n };\n const turnStartRequestedEvent: Omit = {\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n causationEventId: userMessageEvent.eventId,\n type: \"thread.turn-start-requested\",\n payload: {\n threadId: command.threadId,\n messageId: command.message.messageId,\n ...(command.modelSelection !== undefined\n ? { modelSelection: command.modelSelection }\n : {}),\n ...(command.titleSeed !== undefined ? { titleSeed: command.titleSeed } : {}),\n runtimeMode: targetThread.runtimeMode,\n interactionMode: targetThread.interactionMode,\n ...(sourceProposedPlan !== undefined ? { sourceProposedPlan } : {}),\n createdAt: command.createdAt,\n },\n };\n // Real activity resets ANY override: it wakes an explicitly settled\n // thread, and it clears a keep-active pin back to neutral so the\n // thread can auto-settle again after this burst of work goes stale.\n // A snooze clears the same way — sending a message to a snoozed\n // thread is the user re-engaging, so the return ticket is spent.\n const lifecycleResetEvents: Array> = [];\n if (targetThread.settledOverride !== null) {\n lifecycleResetEvents.push({\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.unsettled\",\n payload: {\n threadId: command.threadId,\n reason: \"activity\",\n updatedAt: command.createdAt,\n },\n });\n }\n if (targetThread.snoozedUntil != null) {\n lifecycleResetEvents.push({\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.unsnoozed\",\n payload: {\n threadId: command.threadId,\n reason: \"activity\",\n updatedAt: command.createdAt,\n },\n });\n }\n return [...lifecycleResetEvents, userMessageEvent, turnStartRequestedEvent];", + "checksum": "0d0fe115f9ae7b07e903de3cca6dfd815044b54aa8a56b75417acb4a17410c4d" + }, + "turn-lifecycle-command-reactor": { + "id": "turn-lifecycle-command-reactor", + "path": "apps/server/src/orchestration/Layers/ProviderCommandReactor.ts", + "start": 1060, + "end": 1174, + "language": "typescript", + "label": "Committed turn intent forwarded to the provider", + "code": " const processTurnStartRequested = Effect.fn(\"processTurnStartRequested\")(function* (\n event: Extract,\n ) {\n const key = turnStartKeyForEvent(event);\n if (yield* hasHandledTurnStartRecently(key)) {\n return;\n }\n\n const thread = yield* resolveThread(event.payload.threadId);\n if (!thread) {\n return;\n }\n\n const message = thread.messages.find((entry) => entry.id === event.payload.messageId);\n if (!message || message.role !== \"user\") {\n yield* appendProviderFailureActivity({\n threadId: event.payload.threadId,\n kind: \"provider.turn.start.failed\",\n summary: \"Provider turn start failed\",\n detail: `User message '${event.payload.messageId}' was not found for turn start request.`,\n turnId: null,\n createdAt: event.payload.createdAt,\n });\n return;\n }\n\n const isFirstUserMessageTurn =\n thread.messages.filter((entry) => entry.role === \"user\").length === 1;\n if (isFirstUserMessageTurn) {\n const project = yield* resolveProject(thread.projectId);\n const generationCwd =\n resolveThreadWorkspaceCwd({\n thread,\n projects: project ? [project] : [],\n }) ?? process.cwd();\n const generationInput = {\n messageText: message.text,\n ...(message.attachments !== undefined ? { attachments: message.attachments } : {}),\n ...(event.payload.titleSeed !== undefined ? { titleSeed: event.payload.titleSeed } : {}),\n };\n\n yield* maybeGenerateAndRenameWorktreeBranchForFirstTurn({\n threadId: event.payload.threadId,\n branch: thread.branch,\n worktreePath: thread.worktreePath,\n ...generationInput,\n }).pipe(Effect.forkScoped);\n\n if (canReplaceThreadTitle(thread.title, event.payload.titleSeed)) {\n yield* maybeGenerateThreadTitleForFirstTurn({\n threadId: event.payload.threadId,\n cwd: generationCwd,\n ...generationInput,\n }).pipe(Effect.forkScoped);\n }\n }\n\n const handleTurnStartFailure = (cause: Cause.Cause) => {\n if (Cause.hasInterruptsOnly(cause)) {\n return Effect.void;\n }\n const detail = formatFailureDetail(cause);\n return setThreadSessionErrorOnTurnStartFailure({\n threadId: event.payload.threadId,\n detail,\n createdAt: event.payload.createdAt,\n }).pipe(\n Effect.flatMap(() =>\n appendProviderFailureActivity({\n threadId: event.payload.threadId,\n kind: \"provider.turn.start.failed\",\n summary: \"Provider turn start failed\",\n detail,\n turnId: null,\n createdAt: event.payload.createdAt,\n }),\n ),\n Effect.asVoid,\n );\n };\n\n const recoverTurnStartFailure = (cause: Cause.Cause) =>\n handleTurnStartFailure(cause).pipe(\n Effect.catchCause((recoveryCause) =>\n Effect.logWarning(\"provider command reactor failed to recover turn start failure\", {\n eventType: event.type,\n threadId: event.payload.threadId,\n cause: Cause.pretty(recoveryCause),\n originalCause: Cause.pretty(cause),\n }),\n ),\n );\n\n const sendTurnRequest = yield* buildSendTurnRequestForThread({\n threadId: event.payload.threadId,\n messageText: message.text,\n ...(message.attachments !== undefined ? { attachments: message.attachments } : {}),\n ...(event.payload.modelSelection !== undefined\n ? { modelSelection: event.payload.modelSelection }\n : {}),\n interactionMode: event.payload.interactionMode,\n createdAt: event.payload.createdAt,\n }).pipe(\n Effect.map(Option.some),\n Effect.catchCause((cause) => handleTurnStartFailure(cause).pipe(Effect.as(Option.none()))),\n );\n\n if (Option.isNone(sendTurnRequest)) {\n return;\n }\n\n yield* providerService\n .sendTurn(sendTurnRequest.value)\n .pipe(Effect.catchCause(recoverTurnStartFailure), Effect.forkScoped);\n });", + "checksum": "e612e2a0295ab2afbf9d9b7a9d4c7da0578c4adf5b052b24892d929ec9995f00" + }, + "turn-lifecycle-runtime-correlation": { + "id": "turn-lifecycle-runtime-correlation", + "path": "apps/server/src/provider/Layers/ProviderService.ts", + "start": 195, + "end": 213, + "language": "typescript", + "label": "Provider runtime event identity validation", + "code": "const correlateRuntimeEventWithInstance = (\n source: {\n readonly instanceId: ProviderInstanceId;\n readonly provider: ProviderDriverKind;\n },\n event: ProviderRuntimeEvent,\n): ProviderRuntimeEvent => {\n if (event.provider !== source.provider) {\n throw new Error(\n `ProviderService.streamEvents: provider instance '${source.instanceId}' is backed by driver '${source.provider}' but emitted driver '${event.provider}'.`,\n );\n }\n if (event.providerInstanceId !== undefined && event.providerInstanceId !== source.instanceId) {\n throw new Error(\n `ProviderService.streamEvents: provider instance '${source.instanceId}' emitted event for instance '${event.providerInstanceId}'.`,\n );\n }\n return { ...event, providerInstanceId: source.instanceId };\n};", + "checksum": "43acc45594b4f0975e8a79e5f7a2dd9f0ce5233962b23cbf441038991a1f3082" + }, + "turn-lifecycle-runtime-guards": { + "id": "turn-lifecycle-runtime-guards", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1505, + "end": 1656, + "language": "typescript", + "label": "Runtime lifecycle correlation and durable session folding", + "code": " const now = event.createdAt;\n const eventTurnId = toTurnId(event.turnId);\n const activeTurnId = thread.session?.activeTurnId ?? null;\n const pendingTurnStart = yield* projectionTurnRepository.getPendingTurnStartByThreadId({\n threadId: thread.id,\n });\n const hasPendingTurnStart =\n Option.isSome(pendingTurnStart) && thread.session?.status === \"starting\";\n\n const conflictsWithActiveTurn =\n activeTurnId !== null && eventTurnId !== undefined && !sameId(activeTurnId, eventTurnId);\n const missingTurnForActiveTurn = activeTurnId !== null && eventTurnId === undefined;\n\n // A turn.started that conflicts with the active turn is legitimate when\n // the server itself has a turn start pending for this thread AND the\n // provider session already tracks the event's turn as its active turn:\n // steering a running turn makes some providers (e.g. opencode) open a\n // new turn without ever completing the superseded one. A stale\n // turn.started for some other turn id still gets rejected.\n const conflictingTurnStartIsPendingTurnStart =\n event.type === \"turn.started\" && conflictsWithActiveTurn\n ? sameId(yield* getExpectedProviderTurnIdForThread(thread.id), eventTurnId) &&\n Option.isSome(pendingTurnStart)\n : false;\n\n const shouldApplyThreadLifecycle = (() => {\n if (!STRICT_PROVIDER_LIFECYCLE_GUARD) {\n return true;\n }\n switch (event.type) {\n case \"session.exited\":\n return true;\n case \"session.started\":\n case \"thread.started\":\n return true;\n case \"turn.started\":\n return !conflictsWithActiveTurn || conflictingTurnStartIsPendingTurnStart;\n case \"turn.completed\":\n if (conflictsWithActiveTurn || missingTurnForActiveTurn) {\n return false;\n }\n // Only the active turn may close the lifecycle state.\n if (activeTurnId !== null && eventTurnId !== undefined) {\n return sameId(activeTurnId, eventTurnId);\n }\n // No active turn tracked: accept only completions that name their\n // turn (covers a real completion whose turn.started was lost). An\n // untargeted completion cannot prove it belongs to any turn this\n // thread ran — the known emitter was the Claude resume handshake\n // (system/init + result(num_turns: 0)), which is not a turn at\n // all — and applying it here stomps the \"starting\" lifecycle\n // state while a turn start is pending.\n return eventTurnId !== undefined;\n default:\n return true;\n }\n })();\n const acceptedTurnStartedSourcePlan =\n event.type === \"turn.started\" && shouldApplyThreadLifecycle\n ? yield* getSourceProposedPlanReferenceForAcceptedTurnStart(thread.id, eventTurnId)\n : null;\n\n if (\n event.type === \"session.started\" ||\n event.type === \"session.state.changed\" ||\n event.type === \"session.exited\" ||\n event.type === \"thread.started\" ||\n event.type === \"turn.started\" ||\n event.type === \"turn.completed\"\n ) {\n const status = (() => {\n switch (event.type) {\n case \"session.state.changed\": {\n const runtimeStatus = orchestrationSessionStatusFromRuntimeState(event.payload.state);\n return hasPendingTurnStart && runtimeStatus === \"ready\" ? \"starting\" : runtimeStatus;\n }\n case \"turn.started\":\n return \"running\";\n case \"session.exited\":\n return \"stopped\";\n case \"turn.completed\":\n return normalizeRuntimeTurnState(event.payload.state) === \"failed\"\n ? \"error\"\n : \"ready\";\n case \"session.started\":\n case \"thread.started\":\n // Provider thread/session start notifications can arrive during an\n // active or pending turn; preserve that lifecycle state.\n return activeTurnId !== null ? \"running\" : hasPendingTurnStart ? \"starting\" : \"ready\";\n }\n })();\n const nextActiveTurnId =\n event.type === \"turn.started\"\n ? (eventTurnId ?? null)\n : event.type === \"turn.completed\" || event.type === \"session.exited\"\n ? null\n : event.type === \"session.state.changed\" &&\n !sessionStatusAllowsActiveTurn(\n orchestrationSessionStatusFromRuntimeState(event.payload.state),\n )\n ? null\n : activeTurnId;\n const lastError =\n event.type === \"session.state.changed\" && event.payload.state === \"error\"\n ? (event.payload.reason ?? thread.session?.lastError ?? \"Provider session error\")\n : event.type === \"turn.completed\" &&\n normalizeRuntimeTurnState(event.payload.state) === \"failed\"\n ? (event.payload.errorMessage ?? thread.session?.lastError ?? \"Turn failed\")\n : status === \"ready\"\n ? null\n : (thread.session?.lastError ?? null);\n\n if (shouldApplyThreadLifecycle) {\n if (event.type === \"turn.started\" && acceptedTurnStartedSourcePlan !== null) {\n yield* markSourceProposedPlanImplemented(\n acceptedTurnStartedSourcePlan.sourceThreadId,\n acceptedTurnStartedSourcePlan.sourcePlanId,\n thread.id,\n now,\n ).pipe(\n Effect.catchCause((cause) =>\n Effect.logWarning(\n \"provider runtime ingestion failed to mark source proposed plan\",\n {\n eventId: event.eventId,\n eventType: event.type,\n cause: Cause.pretty(cause),\n },\n ),\n ),\n );\n }\n\n yield* orchestrationEngine.dispatch({\n type: \"thread.session.set\",\n commandId: yield* providerCommandId(event, \"thread-session-set\"),\n threadId: thread.id,\n session: {\n threadId: thread.id,\n status,\n providerName: event.provider,\n ...(event.providerInstanceId !== undefined\n ? { providerInstanceId: event.providerInstanceId }\n : {}),\n runtimeMode: thread.session?.runtimeMode ?? \"full-access\",\n activeTurnId: nextActiveTurnId,\n lastError,\n updatedAt: now,\n },\n createdAt: now,\n });\n }", + "checksum": "c7bc77bba03bd67251974ffa4e634dad8af26720466ddde046f4be45c4110947" + }, + "turn-lifecycle-buffering": { + "id": "turn-lifecycle-buffering", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 1659, + "end": 1750, + "language": "typescript", + "label": "Buffered assistant delivery and pause-boundary flush", + "code": " const assistantDelta =\n event.type === \"content.delta\" && event.payload.streamKind === \"assistant_text\"\n ? event.payload.delta\n : undefined;\n const proposedPlanDelta =\n event.type === \"turn.proposed.delta\" ? event.payload.delta : undefined;\n\n if (assistantDelta && assistantDelta.length > 0) {\n const turnId = toTurnId(event.turnId);\n const assistantMessageId = yield* getOrCreateAssistantMessageId({\n threadId: thread.id,\n event,\n ...(turnId ? { turnId } : {}),\n });\n if (turnId) {\n yield* rememberAssistantMessageId(thread.id, turnId, assistantMessageId);\n }\n\n const assistantDeliveryMode: AssistantDeliveryMode = yield* Effect.map(\n serverSettingsService.getSettings,\n (settings) => (settings.enableLegacyTokenStreaming ? \"streaming\" : \"buffered\"),\n );\n if (assistantDeliveryMode === \"buffered\") {\n const spillChunk = yield* appendBufferedAssistantText(assistantMessageId, assistantDelta);\n if (spillChunk.length > 0) {\n yield* orchestrationEngine.dispatch({\n type: \"thread.message.assistant.delta\",\n commandId: yield* providerCommandId(event, \"assistant-delta-buffer-spill\"),\n threadId: thread.id,\n messageId: assistantMessageId,\n delta: spillChunk,\n ...(turnId ? { turnId } : {}),\n createdAt: now,\n });\n }\n } else {\n yield* orchestrationEngine.dispatch({\n type: \"thread.message.assistant.delta\",\n commandId: yield* providerCommandId(event, \"assistant-delta\"),\n threadId: thread.id,\n messageId: assistantMessageId,\n delta: assistantDelta,\n ...(turnId ? { turnId } : {}),\n createdAt: now,\n });\n }\n }\n\n const pauseForUserTurnId =\n event.type === \"request.opened\" || event.type === \"user-input.requested\"\n ? toTurnId(event.turnId)\n : undefined;\n if (pauseForUserTurnId) {\n const detailedThread = yield* getLoadedThreadDetail();\n const assistantDeliveryMode: AssistantDeliveryMode = yield* Effect.map(\n serverSettingsService.getSettings,\n (settings) => (settings.enableLegacyTokenStreaming ? \"streaming\" : \"buffered\"),\n );\n const flushedMessageIds =\n assistantDeliveryMode === \"buffered\"\n ? yield* flushBufferedAssistantMessagesForTurn({\n event,\n threadId: thread.id,\n turnId: pauseForUserTurnId,\n createdAt: now,\n commandTag:\n event.type === \"request.opened\"\n ? \"assistant-delta-flush-on-request-opened\"\n : \"assistant-delta-flush-on-user-input-requested\",\n })\n : new Set();\n yield* finalizeActiveAssistantSegmentForTurn({\n event,\n threadId: thread.id,\n turnId: pauseForUserTurnId,\n createdAt: now,\n commandTag:\n event.type === \"request.opened\"\n ? \"assistant-complete-on-request-opened\"\n : \"assistant-complete-on-user-input-requested\",\n finalDeltaCommandTag:\n event.type === \"request.opened\"\n ? \"assistant-delta-finalize-on-request-opened\"\n : \"assistant-delta-finalize-on-user-input-requested\",\n hasProjectedMessage:\n detailedThread !== null &&\n hasAssistantMessageForTurn(detailedThread.messages, pauseForUserTurnId, {\n streamingOnly: true,\n }),\n flushedMessageIds,\n });\n }", + "checksum": "e91fb7e11d5c75dc5a834b75c111d8805a0342d7807a62d1977cd0542a51508c" + }, + "turn-lifecycle-interrupt": { + "id": "turn-lifecycle-interrupt", + "path": "apps/server/src/orchestration/decider.ts", + "start": 1039, + "end": 1058, + "language": "typescript", + "label": "Durable turn interrupt intent", + "code": " case \"thread.turn.interrupt\": {\n yield* requireThread({\n readModel,\n command,\n threadId: command.threadId,\n });\n return {\n ...(yield* withEventBase({\n aggregateKind: \"thread\",\n aggregateId: command.threadId,\n occurredAt: command.createdAt,\n commandId: command.commandId,\n })),\n type: \"thread.turn-interrupt-requested\",\n payload: {\n threadId: command.threadId,\n ...(command.turnId !== undefined ? { turnId: command.turnId } : {}),\n createdAt: command.createdAt,\n },\n };", + "checksum": "78ab7a9c85d8c101f2136c38a88c3cef91b00adf35fb3731e56f8537cced4278" + }, + "turn-lifecycle-checkpoint-completion": { + "id": "turn-lifecycle-checkpoint-completion", + "path": "apps/server/src/orchestration/Layers/CheckpointReactor.ts", + "start": 356, + "end": 458, + "language": "typescript", + "label": "Post-turn checkpoint capture and placeholder replacement", + "code": " function* (event: Extract) {\n const turnId = toTurnId(event.turnId);\n if (!turnId) {\n return;\n }\n\n const thread = yield* resolveThreadDetail(event.threadId);\n if (!thread) {\n return;\n }\n\n // When a primary turn is active, only that turn may produce completion checkpoints.\n if (thread.session?.activeTurnId && !sameId(thread.session.activeTurnId, turnId)) {\n return;\n }\n\n // Only skip if a real (non-placeholder) checkpoint already exists for this turn.\n // ProviderRuntimeIngestion may insert placeholder entries with status \"missing\"\n // before this reactor runs; those must not prevent real git capture.\n if (\n thread.checkpoints.some(\n (checkpoint) => checkpoint.turnId === turnId && checkpoint.status !== \"missing\",\n )\n ) {\n return;\n }\n\n const projects = yield* resolveThreadProjects(thread.projectId);\n const checkpointCwd = yield* resolveCheckpointCwd({\n threadId: thread.id,\n thread,\n projects,\n preferSessionRuntime: true,\n });\n if (!checkpointCwd) {\n return;\n }\n\n // If a placeholder checkpoint exists for this turn, reuse its turn count\n // instead of incrementing past it.\n const existingPlaceholder = thread.checkpoints.find(\n (checkpoint) => checkpoint.turnId === turnId && checkpoint.status === \"missing\",\n );\n const currentTurnCount = thread.checkpoints.reduce(\n (maxTurnCount, checkpoint) => Math.max(maxTurnCount, checkpoint.checkpointTurnCount),\n 0,\n );\n const nextTurnCount = existingPlaceholder\n ? existingPlaceholder.checkpointTurnCount\n : currentTurnCount + 1;\n\n yield* captureAndDispatchCheckpoint({\n threadId: thread.id,\n turnId,\n thread,\n cwd: checkpointCwd,\n turnCount: nextTurnCount,\n status: checkpointStatusFromRuntime(event.payload.state),\n assistantMessageId: undefined,\n createdAt: event.createdAt,\n });\n },\n );\n\n // Captures a real git checkpoint when a placeholder checkpoint (status \"missing\")\n // is detected via a domain event. This replaces the placeholder with a real\n // git-ref-based checkpoint.\n //\n // ProviderRuntimeIngestion creates placeholder checkpoints on turn.diff.updated\n // events from the Codex runtime. This handler fires when the corresponding\n // domain event arrives, allowing the reactor to capture the actual filesystem\n // state into a git ref and dispatch a replacement checkpoint.\n const captureCheckpointFromPlaceholder = Effect.fn(\"captureCheckpointFromPlaceholder\")(function* (\n event: Extract,\n ) {\n const { threadId, turnId, checkpointTurnCount, status } = event.payload;\n\n // Only replace placeholders; skip events from our own real captures.\n if (status !== \"missing\") {\n return;\n }\n\n const thread = yield* resolveThreadDetail(threadId);\n if (!thread) {\n yield* Effect.logWarning(\"checkpoint capture from placeholder skipped: thread not found\", {\n threadId,\n });\n return;\n }\n\n // If a real checkpoint already exists for this turn, skip.\n if (\n thread.checkpoints.some(\n (checkpoint) => checkpoint.turnId === turnId && checkpoint.status !== \"missing\",\n )\n ) {\n yield* Effect.logDebug(\n \"checkpoint capture from placeholder skipped: real checkpoint already exists\",\n { threadId, turnId },\n );\n return;\n }\n", + "checksum": "e341d79b8fcb4969bed1f9f6a7ad0b5d032de516eabaa59661d2f8ce698bd3b7" + }, + "permission-runtime-mode-contract": { + "id": "permission-runtime-mode-contract", + "path": "packages/contracts/src/orchestration.ts", + "start": 120, + "end": 143, + "language": "typescript", + "label": "Canonical runtime modes and approval decisions", + "code": "export const RuntimeMode = Schema.Literals([\n \"approval-required\",\n \"auto-accept-edits\",\n \"auto\",\n \"full-access\",\n]);\nexport type RuntimeMode = typeof RuntimeMode.Type;\nexport const DEFAULT_RUNTIME_MODE: RuntimeMode = \"full-access\";\nexport const ProviderInteractionMode = Schema.Literals([\"default\", \"plan\"]);\nexport type ProviderInteractionMode = typeof ProviderInteractionMode.Type;\nexport const DEFAULT_PROVIDER_INTERACTION_MODE: ProviderInteractionMode = \"default\";\nexport const ProviderRequestKind = Schema.Literals([\"command\", \"file-read\", \"file-change\"]);\nexport type ProviderRequestKind = typeof ProviderRequestKind.Type;\nexport const AssistantDeliveryMode = Schema.Literals([\"buffered\", \"streaming\"]);\nexport type AssistantDeliveryMode = typeof AssistantDeliveryMode.Type;\nexport const ProviderApprovalDecision = Schema.Literals([\n \"accept\",\n \"acceptForSession\",\n \"decline\",\n \"cancel\",\n]);\nexport type ProviderApprovalDecision = typeof ProviderApprovalDecision.Type;\nexport const ProviderUserInputAnswers = Schema.Record(Schema.String, Schema.Unknown);\nexport type ProviderUserInputAnswers = typeof ProviderUserInputAnswers.Type;", + "checksum": "2ec2b0f6d38c3c832ef4494cbe97a899fe4f4b83fe808ef16a1356580e935479" + }, + "permission-codex-mode-map": { + "id": "permission-codex-mode-map", + "path": "apps/server/src/provider/Layers/CodexSessionRuntime.ts", + "start": 268, + "end": 340, + "language": "typescript", + "label": "T3 runtime modes mapped into Codex approval and sandbox settings", + "code": "function runtimeModeToThreadConfig(input: RuntimeMode): {\n readonly approvalPolicy: EffectCodexSchema.V2ThreadStartParams__AskForApproval;\n readonly sandbox: EffectCodexSchema.V2ThreadStartParams__SandboxMode;\n // Always explicit: omitting the field on resume keeps the thread's previous\n // reviewer, which would leave auto_review sticky after switching modes.\n readonly approvalsReviewer: EffectCodexSchema.V2ThreadStartParams__ApprovalsReviewer;\n} {\n switch (input) {\n case \"approval-required\":\n return {\n approvalPolicy: \"untrusted\",\n sandbox: \"read-only\",\n approvalsReviewer: \"user\",\n };\n case \"auto-accept-edits\":\n return {\n approvalPolicy: \"on-request\",\n sandbox: \"workspace-write\",\n approvalsReviewer: \"user\",\n };\n case \"auto\":\n return {\n approvalPolicy: \"on-request\",\n sandbox: \"workspace-write\",\n approvalsReviewer: \"auto_review\",\n };\n case \"full-access\":\n default:\n return {\n approvalPolicy: \"never\",\n sandbox: \"danger-full-access\",\n approvalsReviewer: \"user\",\n };\n }\n}\n\nfunction buildThreadStartParams(input: {\n readonly cwd: string;\n readonly runtimeMode: RuntimeMode;\n readonly model: string | undefined;\n readonly serviceTier: CodexServiceTier | undefined;\n}): EffectCodexSchema.V2ThreadStartParams {\n const config = runtimeModeToThreadConfig(input.runtimeMode);\n return {\n cwd: input.cwd,\n approvalPolicy: config.approvalPolicy,\n sandbox: config.sandbox,\n approvalsReviewer: config.approvalsReviewer,\n ...(input.model ? { model: input.model } : {}),\n ...(input.serviceTier ? { serviceTier: input.serviceTier } : {}),\n };\n}\n\nfunction runtimeModeToTurnSandboxPolicy(\n input: RuntimeMode,\n): EffectCodexSchema.V2TurnStartParams__SandboxPolicy {\n switch (input) {\n case \"approval-required\":\n return {\n type: \"readOnly\",\n };\n case \"auto-accept-edits\":\n case \"auto\":\n return {\n type: \"workspaceWrite\",\n };\n case \"full-access\":\n default:\n return {\n type: \"dangerFullAccess\",\n };\n }\n}", + "checksum": "bf3d7a104fb45d37eee289512fb96dc72046d830c24c5eda45fdd42346b519d9" + }, + "permission-request-contract": { + "id": "permission-request-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 430, + "end": 469, + "language": "typescript", + "label": "Canonical approval and structured-input request payloads", + "code": "const RequestOpenedPayload = Schema.Struct({\n requestType: CanonicalRequestType,\n detail: Schema.optional(TrimmedNonEmptyStringSchema),\n args: Schema.optional(Schema.Unknown),\n});\nexport type RequestOpenedPayload = typeof RequestOpenedPayload.Type;\n\nconst RequestResolvedPayload = Schema.Struct({\n requestType: CanonicalRequestType,\n decision: Schema.optional(TrimmedNonEmptyStringSchema),\n resolution: Schema.optional(Schema.Unknown),\n});\nexport type RequestResolvedPayload = typeof RequestResolvedPayload.Type;\n\nconst UserInputQuestionOption = Schema.Struct({\n label: TrimmedNonEmptyStringSchema,\n description: TrimmedNonEmptyStringSchema,\n});\nexport type UserInputQuestionOption = typeof UserInputQuestionOption.Type;\n\nexport const UserInputQuestion = Schema.Struct({\n id: TrimmedNonEmptyStringSchema,\n header: TrimmedNonEmptyStringSchema,\n question: TrimmedNonEmptyStringSchema,\n options: Schema.Array(UserInputQuestionOption),\n multiSelect: Schema.optional(Schema.Boolean).pipe(\n Schema.withConstructorDefault(Effect.succeed(false)),\n ),\n});\nexport type UserInputQuestion = typeof UserInputQuestion.Type;\n\nconst UserInputRequestedPayload = Schema.Struct({\n questions: Schema.Array(UserInputQuestion),\n});\nexport type UserInputRequestedPayload = typeof UserInputRequestedPayload.Type;\n\nconst UserInputResolvedPayload = Schema.Struct({\n answers: UnknownRecordSchema,\n});\nexport type UserInputResolvedPayload = typeof UserInputResolvedPayload.Type;", + "checksum": "6b1a92d91a1044987815a33034c9d57cf408dde2c10b3b0d1a518d7c63094277" + }, + "work-task-usage-contract": { + "id": "work-task-usage-contract", + "path": "packages/contracts/src/providerRuntime.ts", + "start": 471, + "end": 543, + "language": "typescript", + "label": "Typed per-task usage and agent-versus-background classification", + "code": "/**\n * Typed per-task usage rollup. Field names match the orchestration-v2 subagent\n * usage vocabulary (#4779) so the eventual migration is a rename, not a remap.\n * Claude reports per-activation deltas; Codex reports cumulative totals — the\n * merge strategy is provider-specific and lives in client-runtime.\n */\nexport const RuntimeTaskUsage = Schema.Struct({\n totalTokens: NonNegativeInt,\n inputTokens: Schema.optional(NonNegativeInt),\n cachedInputTokens: Schema.optional(NonNegativeInt),\n outputTokens: Schema.optional(NonNegativeInt),\n reasoningOutputTokens: Schema.optional(NonNegativeInt),\n toolUses: Schema.optional(NonNegativeInt),\n durationMs: Schema.optional(NonNegativeInt),\n});\nexport type RuntimeTaskUsage = typeof RuntimeTaskUsage.Type;\n\nexport const TaskWorkflowPhase = Schema.Struct({\n index: NonNegativeInt,\n title: TrimmedNonEmptyStringSchema,\n});\nexport type TaskWorkflowPhase = typeof TaskWorkflowPhase.Type;\n\nexport const TaskRunHandles = Schema.Struct({\n runId: Schema.optional(TrimmedNonEmptyStringSchema),\n scriptPath: Schema.optional(TrimmedNonEmptyStringSchema),\n transcriptDir: Schema.optional(TrimmedNonEmptyStringSchema),\n /** Only http/https URLs may be stored here — sanitized at the adapter. */\n sessionUrl: Schema.optional(TrimmedNonEmptyStringSchema),\n});\nexport type TaskRunHandles = typeof TaskRunHandles.Type;\n\n/**\n * Watch-loop task types: Monitor-tool tasks plus background shells (a shell\n * that outlives its turn is in practice a watch loop). Canonical single copy —\n * the server liveness registry, ingestion's agentKind stamp, and the client\n * fold's legacy fallback all classify with these sets.\n */\nexport const MONITOR_TASK_TYPES: ReadonlySet = new Set([\n \"monitor\",\n \"monitor_mcp\",\n \"local_bash\",\n \"shell\",\n]);\n/** Task types that are neither agents nor watch loops (plan-mode bookkeeping). */\nexport const INERT_TASK_TYPES: ReadonlySet = new Set([\"plan\", \"dream\"]);\n\n/**\n * Agent-vs-background classification, stamped by ingestion as `agentKind` so\n * persisted rows are self-describing. A deliberate denylist: the SDK's\n * agent-flavored type names drift (subagent, local_agent, local_workflow, …)\n * and an allowlist silently dropped real subagents when \"local_agent\"\n * appeared. A task launched from inside a subagent (agentId set) is\n * agent-internal background work UNLESS it is itself agent-flavored — a\n * nested agent can outlive its parent and stays in the roster.\n */\nexport function classifyTaskAgentKind(input: {\n readonly taskType?: string | undefined;\n readonly agentId?: string | undefined;\n}): \"agent\" | \"background\" {\n const { taskType, agentId } = input;\n const nonAgentType =\n taskType !== undefined && (MONITOR_TASK_TYPES.has(taskType) || INERT_TASK_TYPES.has(taskType));\n if (agentId !== undefined && agentId.trim().length > 0) {\n return taskType === undefined || nonAgentType ? \"background\" : \"agent\";\n }\n return nonAgentType ? \"background\" : \"agent\";\n}\n\n/**\n * Optional agent-identity linkage carried on every task lifecycle payload.\n * Repeated on progress and terminal rows (not just start) so client folds can\n * reconstruct an agent even when its start row aged out of activity retention.", + "checksum": "9c7794660442c1d9a47d1553b18d8e593f52d0f6f4ded9f377c395421336aab5" + }, + "work-task-latest-activities": { + "id": "work-task-latest-activities", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 569, + "end": 646, + "language": "typescript", + "label": "Separate stable task progress and usage activity snapshots", + "code": " const linkage = taskLinkageActivityFields(event.payload as Record);\n // Usage and activity are independent latest-state streams. Keeping them\n // under separate stable ids prevents a command/reasoning update from\n // replacing the last known token count (and prevents a usage-only tick\n // from blanking the last meaningful activity).\n const identityLinkage = { ...linkage };\n delete identityLinkage.typedUsage;\n delete identityLinkage.status;\n delete identityLinkage.error;\n const title =\n event.payload.description.trim().length > 0\n ? { title: truncateDetail(event.payload.description, 120) }\n : {};\n const hasProgressState =\n event.payload.typedUsage === undefined ||\n event.payload.summary !== undefined ||\n event.payload.lastToolName !== undefined ||\n event.payload.status !== undefined ||\n event.payload.error !== undefined;\n return [\n ...(hasProgressState\n ? [\n {\n // Stable per-task id: activity is \"latest state\", not\n // history, so each meaningful tick replaces the last. This\n // bounds a large fleet to one activity row per task.\n id: EventId.make(`task-progress:${event.threadId}:${event.payload.taskId}`),\n createdAt: event.createdAt,\n tone: \"info\" as const,\n kind: \"task.progress\" as const,\n summary:\n event.payload.description.trim().length > 0\n ? truncateDetail(event.payload.description, 120)\n : \"Reasoning update\",\n payload: {\n taskId: event.payload.taskId,\n ...title,\n detail: truncateDetail(event.payload.summary ?? event.payload.description),\n ...(event.payload.summary\n ? { summary: truncateDetail(event.payload.summary) }\n : {}),\n ...(event.payload.lastToolName\n ? { lastToolName: event.payload.lastToolName }\n : {}),\n ...(event.payload.status ? { status: event.payload.status } : {}),\n ...(event.payload.error ? { error: event.payload.error } : {}),\n ...(event.payload.usage !== undefined ? { usage: event.payload.usage } : {}),\n ...identityLinkage,\n },\n turnId: toTurnId(event.turnId) ?? null,\n ...maybeSequence,\n },\n ]\n : []),\n ...(event.payload.typedUsage !== undefined\n ? [\n {\n id: EventId.make(`task-usage:${event.threadId}:${event.payload.taskId}`),\n createdAt: event.createdAt,\n tone: \"info\" as const,\n kind: \"task.progress\" as const,\n summary: \"Task usage updated\",\n payload: {\n taskId: event.payload.taskId,\n ...title,\n ...identityLinkage,\n usageSnapshot: true,\n typedUsage: event.payload.typedUsage,\n },\n turnId: toTurnId(event.turnId) ?? null,\n ...maybeSequence,\n },\n ]\n : []),\n ];\n }\n\n case \"task.updated\": {", + "checksum": "11d184eb4842e6907a766a04a86a1b355065eb1ae64b2891b58d24d836acd812" + }, + "work-subagent-usage-merge": { + "id": "work-subagent-usage-merge", + "path": "packages/client-runtime/src/state/subagentRuntime.ts", + "start": 149, + "end": 225, + "language": "typescript", + "label": "Tolerant field-wise task usage parsing and max merge", + "code": "function asUsage(value: unknown): SubagentUsage | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const record = value as Record;\n const totalTokens = asCount(record.totalTokens);\n if (totalTokens === undefined) {\n return undefined;\n }\n const usage: {\n totalTokens: number;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n reasoningOutputTokens?: number;\n toolUses?: number;\n durationMs?: number;\n } = { totalTokens };\n const inputTokens = asCount(record.inputTokens);\n if (inputTokens !== undefined) usage.inputTokens = inputTokens;\n const cachedInputTokens = asCount(record.cachedInputTokens);\n if (cachedInputTokens !== undefined) usage.cachedInputTokens = cachedInputTokens;\n const outputTokens = asCount(record.outputTokens);\n if (outputTokens !== undefined) usage.outputTokens = outputTokens;\n const reasoningOutputTokens = asCount(record.reasoningOutputTokens);\n if (reasoningOutputTokens !== undefined) usage.reasoningOutputTokens = reasoningOutputTokens;\n const toolUses = asCount(record.toolUses);\n if (toolUses !== undefined) usage.toolUses = toolUses;\n const durationMs = asCount(record.durationMs);\n if (durationMs !== undefined) usage.durationMs = durationMs;\n return usage;\n}\n\n/**\n * Provider-specific usage merge (#4779 semantics, verbatim):\n * - max-merge (Codex-style cumulative frames): field-wise maximum, idempotent\n * under duplicate or late frames. Cumulative totals never shrink.\n * - accumulate (Claude-style activation deltas): not needed at this layer —\n * Claude's task_progress usage is itself cumulative per task, so the fold\n * also max-merges. The distinction matters when v2 sums activations.\n * Field-wise: a terminal payload carrying only totalTokens must not wipe a\n * known breakdown.\n */\nfunction mergeUsageMax(\n current: SubagentUsage | null,\n incoming: SubagentUsage | undefined,\n): SubagentUsage | null {\n if (!incoming) {\n return current;\n }\n if (!current) {\n return incoming;\n }\n const pick = (a: number | undefined, b: number | undefined): number | undefined =>\n a === undefined ? b : b === undefined ? a : Math.max(a, b);\n const merged: {\n totalTokens: number;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n reasoningOutputTokens?: number;\n toolUses?: number;\n durationMs?: number;\n } = { totalTokens: Math.max(current.totalTokens, incoming.totalTokens) };\n const inputTokens = pick(current.inputTokens, incoming.inputTokens);\n if (inputTokens !== undefined) merged.inputTokens = inputTokens;\n const cachedInputTokens = pick(current.cachedInputTokens, incoming.cachedInputTokens);\n if (cachedInputTokens !== undefined) merged.cachedInputTokens = cachedInputTokens;\n const outputTokens = pick(current.outputTokens, incoming.outputTokens);\n if (outputTokens !== undefined) merged.outputTokens = outputTokens;\n const reasoningOutputTokens = pick(current.reasoningOutputTokens, incoming.reasoningOutputTokens);\n if (reasoningOutputTokens !== undefined) merged.reasoningOutputTokens = reasoningOutputTokens;\n const toolUses = pick(current.toolUses, incoming.toolUses);\n if (toolUses !== undefined) merged.toolUses = toolUses;\n const durationMs = pick(current.durationMs, incoming.durationMs);\n if (durationMs !== undefined) merged.durationMs = durationMs;\n return merged;", + "checksum": "0c82d5cb0342b54d4564be5359be4c6368ac86bfeb618d455edd558a5e3645a7" + }, + "context-provider-binding-shape": { + "id": "context-provider-binding-shape", + "path": "apps/server/src/persistence/ProviderSessionRuntime.ts", + "start": 35, + "end": 110, + "language": "typescript", + "label": "Persisted provider-instance binding and opaque continuation state", + "code": "export const ProviderSessionRuntime = Schema.Struct({\n threadId: ThreadId,\n providerName: Schema.String,\n /**\n * User-defined routing key for the configured provider instance that\n * owns this session. Nullable only at the storage/migration boundary:\n * rows persisted before the driver/instance split carry only\n * `providerName`. Repository consumers must materialize a concrete\n * instance id before routing.\n */\n providerInstanceId: Schema.NullOr(ProviderInstanceId),\n adapterKey: Schema.String,\n runtimeMode: RuntimeMode,\n status: ProviderSessionRuntimeStatus,\n lastSeenAt: IsoDateTime,\n resumeCursor: Schema.NullOr(Schema.Unknown),\n runtimePayload: Schema.NullOr(Schema.Unknown),\n});\nexport type ProviderSessionRuntime = typeof ProviderSessionRuntime.Type;\n\nexport const GetProviderSessionRuntimeInput = Schema.Struct({ threadId: ThreadId });\nexport type GetProviderSessionRuntimeInput = typeof GetProviderSessionRuntimeInput.Type;\n\nexport const DeleteProviderSessionRuntimeInput = Schema.Struct({ threadId: ThreadId });\nexport type DeleteProviderSessionRuntimeInput = typeof DeleteProviderSessionRuntimeInput.Type;\n\n/**\n * ProviderSessionRuntimeRepository - Service tag for provider runtime persistence.\n */\nexport class ProviderSessionRuntimeRepository extends Context.Service<\n ProviderSessionRuntimeRepository,\n {\n /**\n * Insert or replace a provider runtime row.\n *\n * Upserts by canonical `threadId`, including JSON payload/cursor fields.\n */\n readonly upsert: (\n runtime: ProviderSessionRuntime,\n ) => Effect.Effect;\n\n /**\n * Read provider runtime state by canonical thread id.\n */\n readonly getByThreadId: (\n input: GetProviderSessionRuntimeInput,\n ) => Effect.Effect<\n Option.Option,\n ProviderSessionRuntimeRepositoryError\n >;\n\n /**\n * List all provider runtime rows.\n *\n * Returned in ascending last-seen order.\n */\n readonly list: () => Effect.Effect<\n ReadonlyArray,\n ProviderSessionRuntimeRepositoryError\n >;\n\n /**\n * Delete provider runtime state by canonical thread id.\n */\n readonly deleteByThreadId: (\n input: DeleteProviderSessionRuntimeInput,\n ) => Effect.Effect;\n }\n>()(\"t3/persistence/ProviderSessionRuntime/ProviderSessionRuntimeRepository\") {}\n\nconst ProviderSessionRuntimeDbRowSchema = ProviderSessionRuntime.mapFields(\n Struct.assign({\n resumeCursor: Schema.NullOr(Schema.fromJsonString(Schema.Unknown)),\n runtimePayload: Schema.NullOr(Schema.fromJsonString(Schema.Unknown)),\n }),\n);", + "checksum": "b92dc6c01460eee6a905a51d0d848df3b28fd4410a9403789699bc459815cadd" + }, + "context-memory-compaction-ingestion": { + "id": "context-memory-compaction-ingestion", + "path": "apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts", + "start": 744, + "end": 763, + "language": "typescript", + "label": "Provider compaction observation becomes durable thread activity", + "code": " case \"thread.state.changed\": {\n if (event.payload.state !== \"compacted\") {\n return [];\n }\n\n return [\n {\n id: event.eventId,\n createdAt: event.createdAt,\n tone: \"info\",\n kind: \"context-compaction\",\n summary: \"Context compacted\",\n payload: {\n state: event.payload.state,\n ...(event.payload.detail !== undefined ? { detail: event.payload.detail } : {}),\n },\n turnId: toTurnId(event.turnId) ?? null,\n ...maybeSequence,\n },\n ];", + "checksum": "84f0ec54be712d09ef6dc181bcd36318a26e36de8def7182a8377454dd21fcdd" + }, + "context-window-reducer-retention": { + "id": "context-window-reducer-retention", + "path": "packages/client-runtime/src/state/threadReducer.ts", + "start": 562, + "end": 592, + "language": "typescript", + "label": "Latest resolvable context-window snapshot retained per turn id", + "code": " // ── Activities ──────────────────────────────────────────────────\n case \"thread.activity-appended\": {\n const activity = event.payload.activity;\n // A resolvable context-window update supersedes earlier resolvable ones\n // for the same turn: consumers only read the latest value (walking the\n // array backwards), and providers stream these updates continuously, so\n // retaining the history grows the thread by thousands of rows over a\n // long session. Mirrors the server-side snapshot rule in\n // dropStaleContextWindowActivities; retention stays per turn so a\n // thread.reverted that discards turns can still resolve a value from\n // the turns that survive.\n const supersedesContextWindow = isResolvableContextWindowActivity(activity);\n const activities = pipe(\n thread.activities,\n Arr.filter(\n (entry) =>\n entry.id !== activity.id &&\n !(\n supersedesContextWindow &&\n entry.turnId === activity.turnId &&\n isResolvableContextWindowActivity(entry)\n ),\n ),\n Arr.append(activity),\n Arr.sort(activityOrder),\n );\n\n return {\n kind: \"updated\",\n thread: { ...thread, activities, updatedAt: event.occurredAt },\n };", + "checksum": "ae9a3e3858741dd9a80e70b34a5ab36dca52539d93e1b199f9572b7113f6c995" + }, + "workbench-terminal-attach-order": { + "id": "workbench-terminal-attach-order", + "path": "apps/server/src/terminal/Manager.ts", + "start": 2351, + "end": 2402, + "language": "typescript", + "label": "Terminal attach buffers races, emits a snapshot, then delivers live events", + "code": " const attachStream: TerminalManager[\"Service\"][\"attachStream\"] = (input, listener) => {\n let unsubscribe: (() => void) | null = null;\n\n return Effect.gen(function* () {\n const bufferedEvents: TerminalEvent[] = [];\n let deliverLive = false;\n\n unsubscribe = yield* subscribe((event) => {\n if (event.threadId !== input.threadId || event.terminalId !== input.terminalId) {\n return Effect.void;\n }\n\n if (!deliverLive) {\n bufferedEvents.push(event);\n return Effect.void;\n }\n\n const attachEvent = terminalEventToAttachEvent(event);\n return attachEvent ? listener(attachEvent) : Effect.void;\n });\n\n const initialSnapshot = yield* openOrAttachForStream(input);\n\n yield* listener({\n type: \"snapshot\",\n snapshot: initialSnapshot,\n });\n\n for (const event of bufferedEvents) {\n if (isDuplicateAttachSnapshotEvent(event, initialSnapshot)) {\n continue;\n }\n\n const attachEvent = terminalEventToAttachEvent(event);\n if (attachEvent) {\n yield* listener(attachEvent);\n }\n }\n\n deliverLive = true;\n return () => {\n unsubscribe?.();\n unsubscribe = null;\n };\n }).pipe(\n Effect.catchCause((cause) =>\n Effect.flatMap(\n Effect.sync(() => {\n unsubscribe?.();\n unsubscribe = null;\n }),\n () => Effect.failCause(cause),", + "checksum": "b271e39c3ccce7f5ba8015d4dc72f7ca64041d9d6ec6d4c91bdbbba668800ba9" + }, + "workbench-asset-token-verification": { + "id": "workbench-asset-token-verification", + "path": "apps/server/src/assets/AssetAccess.ts", + "start": 410, + "end": 451, + "language": "typescript", + "label": "Asset URL signing followed by signature and expiry verification", + "code": " cause,\n }),\n ),\n );\n if (claims.kind === \"project-favicon\" || claims.kind === \"project-favicon-external\") {\n const issuedAt = yield* Clock.currentTimeMillis;\n expiresAt =\n (Math.floor(issuedAt / PROJECT_FAVICON_TOKEN_BUCKET_MS) + 2) *\n PROJECT_FAVICON_TOKEN_BUCKET_MS;\n claims = { ...claims, expiresAt };\n }\n const encodedPayload = base64UrlEncode(encodeAssetClaims(claims));\n const token = `${encodedPayload}.${signPayload(encodedPayload, signingSecret)}`;\n return {\n relativeUrl: `${ASSET_ROUTE_PREFIX}/${token}/${encodeURIComponent(fileName)}`,\n expiresAt,\n ...(sourcePath !== undefined ? { sourcePath } : {}),\n };\n});\n\nexport const resolveAsset = Effect.fn(\"AssetAccess.resolveAsset\")(function* (\n token: string,\n relativePath: string,\n) {\n const [encodedPayload, signature] = token.split(\".\");\n if (!encodedPayload || !signature) return null;\n\n const secretStore = yield* ServerSecretStore.ServerSecretStore;\n const signingSecret = yield* secretStore.getOrCreateRandom(SIGNING_SECRET_NAME, 32).pipe(\n Effect.tapError((cause) => Effect.logError(\"Failed to load the asset signing key.\", { cause })),\n Effect.orElseSucceed(() => null),\n );\n if (!signingSecret) return null;\n if (!timingSafeEqualBase64Url(signature, signPayload(encodedPayload, signingSecret))) return null;\n\n const claims = decodeClaims(encodedPayload);\n if (!claims || claims.expiresAt <= (yield* Clock.currentTimeMillis)) return null;\n\n if (claims.kind === \"attachment\") {\n const config = yield* ServerConfig.ServerConfig;\n const attachmentPath = resolveAttachmentPathById({\n attachmentsDir: config.attachmentsDir,", + "checksum": "27cc3e4c869c07078758c87260ae1f162edb77abdb33fd820bf5a612faef5e3a" + }, + "workbench-mcp-credential-issue": { + "id": "workbench-mcp-credential-issue", + "path": "apps/server/src/mcp/McpSessionRegistry.ts", + "start": 112, + "end": 168, + "language": "typescript", + "label": "Random MCP bearer credential and registry-generated scoped session identity", + "code": " const next = new Map(\n Array.from(records).filter(\n ([, record]) => timestamp - record.lastAliveAt <= livenessWindowMs,\n ),\n );\n return next.size === records.size ? records : next;\n };\n\n const issue: McpSessionRegistryShape[\"issue\"] = Effect.fn(\"McpSessionRegistry.issue\")(\n function* (request) {\n const issuedAt = yield* currentTimeMillis;\n const providerSessionId = yield* crypto.randomUUIDv4.pipe(Effect.orDie);\n const rawToken = yield* crypto.randomBytes(32).pipe(Effect.map(tokenFromBytes), Effect.orDie);\n const tokenHash = yield* hashToken(rawToken);\n const scope: McpInvocationContext.McpInvocationScope = {\n environmentId,\n threadId: ThreadId.make(request.threadId),\n providerSessionId,\n providerInstanceId: ProviderInstanceId.make(request.providerInstanceId),\n capabilities: new Set([\"preview\"]),\n issuedAt,\n };\n yield* SynchronizedRef.update(state, ({ records }) => {\n const next = new Map(pruneDead(records, issuedAt));\n next.set(tokenHash, { tokenHash, scope, lastAliveAt: issuedAt });\n return { records: next };\n });\n return {\n config: {\n environmentId,\n threadId: scope.threadId,\n providerSessionId,\n providerInstanceId: scope.providerInstanceId,\n endpoint,\n authorizationHeader: `Bearer ${rawToken}`,\n },\n };\n },\n );\n\n const resolve: McpSessionRegistryShape[\"resolve\"] = Effect.fn(\"McpSessionRegistry.resolve\")(\n function* (rawToken) {\n if (rawToken.length === 0) return undefined;\n const tokenHash = yield* hashToken(rawToken);\n const timestamp = yield* currentTimeMillis;\n return yield* SynchronizedRef.modify(state, ({ records }) => {\n const current = pruneDead(records, timestamp);\n const record = current.get(tokenHash);\n if (!record) return [undefined, { records: current }] as const;\n const next = new Map(current);\n next.set(tokenHash, { ...record, lastAliveAt: timestamp });\n return [record.scope, { records: next }] as const;\n });\n },\n );\n\n const touch: McpSessionRegistryShape[\"touch\"] = Effect.fn(\"McpSessionRegistry.touch\")(", + "checksum": "1c72aab293661e234f0a570d76f7c90b77c75b4982796ae2258b258060022cb0" + }, + "workbench-pr-write-gates": { + "id": "workbench-pr-write-gates", + "path": "apps/server/src/pullRequest/PullRequestService.ts", + "start": 1300, + "end": 1367, + "language": "typescript", + "label": "Pull-request host capability checks followed by fresh viewer authorization", + "code": " const runAction: PullRequestService[\"Service\"][\"runAction\"] = (input) =>\n requireProject(input).pipe(\n Effect.flatMap((project): Effect.Effect => {\n // The surface hides what a host cannot do, and this refuses it as well: a request that\n // reached here anyway must not be handed to a provider that never claimed the action.\n if (!project.api.capabilities.actions.includes(input.action)) {\n return Effect.fail(\n new PullRequestOperationError({\n operation: \"runAction\",\n detail: `This host cannot ${input.action} a change request.`,\n }),\n );\n }\n // A strategy the host does not offer must be refused rather than passed on: every\n // provider maps an unrecognised method to its own default, so asking Azure DevOps to\n // rebase would quietly merge instead of failing.\n if (\n input.mergeMethod !== undefined &&\n !project.api.capabilities.mergeMethods.includes(input.mergeMethod)\n ) {\n return Effect.fail(\n new PullRequestOperationError({\n operation: \"runAction\",\n detail: `This host cannot merge with the ${input.mergeMethod} strategy.`,\n }),\n );\n }\n // The same for the way a stale branch is brought up to date: a host that only merges\n // must not be asked to rebase and left to pick something else.\n if (\n input.updateMethod !== undefined &&\n !(project.api.capabilities.updateMethods ?? []).includes(input.updateMethod)\n ) {\n return Effect.fail(\n new PullRequestOperationError({\n operation: \"runAction\",\n detail: `This host cannot update a branch by ${input.updateMethod}.`,\n }),\n );\n }\n // What the host can do and what this account may ask of it are two questions, and both\n // have to say yes. The second is asked last, because it costs a request and the checks\n // above do not.\n return viewerPermissionsOf(project, input, \"runAction\").pipe(\n Effect.flatMap((viewer): Effect.Effect => {\n if (!viewer.actions.includes(input.action)) {\n return Effect.fail(\n new PullRequestOperationError({\n operation: \"runAction\",\n detail: ACTION_ACCESS_REFUSALS[input.action],\n }),\n );\n }\n if (\n input.updateMethod !== undefined &&\n !(viewer.updateMethods ?? []).includes(input.updateMethod)\n ) {\n return Effect.fail(\n new PullRequestOperationError({\n operation: \"runAction\",\n detail: ACTION_ACCESS_REFUSALS[\"update-branch\"],\n }),\n );\n }\n return project.api\n .runAction({\n cwd: project.project.workspaceRoot,\n repository: project.repository,", + "checksum": "a76b545059b2edbfff26945859bf1c0085707d87b6d1d2ee395be300619adc6a" + }, + "project-script-import-flow": { + "id": "project-script-import-flow", + "path": "apps/web/src/components/ProjectScriptsControl.tsx", + "start": 80, + "end": 150, + "language": "tsx", + "label": "Checked-in t3.json actions are deduplicated import suggestions", + "code": " const importableScripts = useMemo(\n () =>\n fileScripts.filter(\n (fileScript) =>\n !scripts.some(\n (script) =>\n script.command === fileScript.command ||\n script.name.toLowerCase() === fileScript.name.toLowerCase(),\n ),\n ),\n [fileScripts, scripts],\n );\n const dropdownItemClassName =\n \"data-highlighted:bg-transparent data-highlighted:text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground data-highlighted:hover:bg-accent data-highlighted:hover:text-accent-foreground data-highlighted:focus-visible:bg-accent data-highlighted:focus-visible:text-accent-foreground\";\n\n const openAddDialog = () => {\n setEditorRequest({ scriptId: null, initial: EMPTY_PROJECT_SCRIPT_INPUT });\n };\n\n const openEditDialog = (script: ProjectScript) => {\n setActionsMenuOpen({ scripts: false, imports: false });\n setEditorRequest(editorRequestForScript(script, keybindings));\n };\n\n const submitScript = useCallback(\n (scriptId: string | null, input: NewProjectScriptInput) =>\n scriptId === null ? onAddScript(input) : onUpdateScript(scriptId, input),\n [onAddScript, onUpdateScript],\n );\n\n const importFileScript = async (fileScript: T3ProjectFileScript) => {\n const payload: NewProjectScriptInput = {\n name: fileScript.name,\n command: fileScript.command,\n icon: fileScript.icon ?? \"play\",\n runOnWorktreeCreate: fileScript.runOnWorktreeCreate ?? false,\n keybinding: null,\n previewUrl: fileScript.previewUrl ?? null,\n autoOpenPreview: fileScript.previewUrl ? (fileScript.autoOpenPreview ?? false) : false,\n };\n const result = await onAddScript(payload);\n if (result._tag === \"Failure\" && !isAtomCommandInterrupted(result)) {\n // Surface the failure through the regular add dialog, prefilled so the\n // user can adjust and retry.\n const error = squashAtomCommandFailure(result);\n setEditorRequest({\n scriptId: null,\n initial: payload,\n error: error instanceof Error ? error.message : \"Failed to import action.\",\n });\n }\n };\n\n const importMenuItems = importableScripts.length > 0 && (\n <>\n {primaryScript && }\n \n From t3.json\n {importableScripts.map((fileScript) => (\n void importFileScript(fileScript)}\n >\n \n {fileScript.name}\n \n \n \n \n ))}", + "checksum": "a21e41ea3772e4d8fafeaae8d60da9b9101bcc26a4891e02ec8283b31351b603" + }, + "web-main-runtime-entry": { + "id": "web-main-runtime-entry", + "path": "apps/web/src/main.tsx", + "start": 1, + "end": 61, + "language": "tsx", + "label": "Electron-aware history and authenticated React entry", + "code": "import React from \"react\";\nimport ReactDOM from \"react-dom/client\";\nimport { ClerkProvider } from \"@clerk/react\";\nimport { passkeys } from \"@clerk/electron/passkeys\";\nimport { ClerkProvider as ElectronClerkProvider } from \"@clerk/electron/react\";\nimport { createHashHistory, createBrowserHistory } from \"@tanstack/react-router\";\n\nimport \"./index.css\";\n\nimport { isElectron } from \"./env\";\nimport { ManagedRelayAuthProvider } from \"./cloud/managedAuth\";\nimport { hasCloudPublicConfig } from \"./cloud/publicConfig\";\nimport { getRouter } from \"./router\";\nimport {\n syncDocumentElectronPlatformClasses,\n syncDocumentWindowControlsOverlayClass,\n} from \"./lib/windowControlsOverlay\";\nimport { AppRoot } from \"./AppRoot\";\nimport { clerkAppearance } from \"./components/clerk/clerkAppearance\";\n\n// Electron loads the app from a file-backed shell, so hash history avoids path resolution issues.\nconst history = isElectron ? createHashHistory() : createBrowserHistory();\n\nconst router = getRouter(history);\n\nif (isElectron) {\n syncDocumentElectronPlatformClasses(navigator.platform);\n syncDocumentWindowControlsOverlayClass();\n}\n\nconst clerkPublishableKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY as string | undefined;\n\n// First Clerk UI build containing https://github.com/clerk/javascript/pull/9500.\nconst electronClerkUI = {\n __internal_clerkUIVersion: \"1.30.5-canary.v20260819050620\",\n};\n\nconst app = ;\n\nReactDOM.createRoot(document.getElementById(\"root\") as HTMLElement).render(\n \n {clerkPublishableKey && hasCloudPublicConfig() ? (\n isElectron ? (\n \n {app}\n \n ) : (\n \n {app}\n \n )\n ) : (\n app\n )}\n ,\n);", + "checksum": "469fcbadd4accb57b28f26730ae794e728586908360a345a42ebe3d8dd708f4d" + }, + "web-app-root-providers": { + "id": "web-app-root-providers", + "path": "apps/web/src/AppRoot.tsx", + "start": 1, + "end": 23, + "language": "tsx", + "label": "Shared atom registry and route-persistent renderer hosts", + "code": "import { RouterProvider } from \"@tanstack/react-router\";\n\nimport { ElectronBrowserHost } from \"./browser/ElectronBrowserHost\";\nimport { PreviewAutomationHosts } from \"./components/preview/PreviewAutomationHosts\";\nimport { QuitHoldOverlay } from \"./components/QuitHoldOverlay\";\nimport { AppAtomRegistryProvider } from \"./rpc/atomRegistry\";\nimport type { AppRouter } from \"./router\";\n\n/**\n * Owns renderer-wide providers. The Electron browser host intentionally sits\n * outside the router so its webviews survive route transitions, but it must\n * share the same atom registry as routed UI.\n */\nexport function AppRoot({ router }: { readonly router: AppRouter }) {\n return (\n \n \n \n \n \n \n );\n}", + "checksum": "73f37a466b15084db5148de417c21c833ee135b61b66e955032c4d47d8537b48" + }, + "web-router-composition": { + "id": "web-router-composition", + "path": "apps/web/src/router.ts", + "start": 1, + "end": 20, + "language": "typescript", + "label": "Generated route-tree router construction", + "code": "import { createRouter, RouterHistory } from \"@tanstack/react-router\";\n\nimport { routeTree } from \"./routeTree.gen\";\n\nexport function getRouter(history: RouterHistory) {\n return createRouter({\n routeTree,\n history,\n context: {},\n });\n}\n\nexport type AppRouter = ReturnType;\n\ndeclare module \"@tanstack/react-router\" {\n interface Register {\n router: AppRouter;\n }\n}\n", + "checksum": "0327fd93597b643fc4e5addbe87d4d74fa8a7310fca94e256569285cf8836979" + }, + "web-environment-atom-catalog": { + "id": "web-environment-atom-catalog", + "path": "apps/web/src/connection/catalog.ts", + "start": 1, + "end": 5, + "language": "typescript", + "label": "Web environment catalog uses the shared atom runtime", + "code": "import { createEnvironmentCatalogAtoms } from \"@t3tools/client-runtime/state/connections\";\n\nimport { connectionAtomRuntime } from \"./runtime\";\n\nexport const environmentCatalog = createEnvironmentCatalogAtoms(connectionAtomRuntime);", + "checksum": "94a883ffc47ef7abafabccb826775bb943383795beb4b3e65b75c15604ce5124" + }, + "web-environment-session-atoms": { + "id": "web-environment-session-atoms", + "path": "apps/web/src/state/session.ts", + "start": 7, + "end": 41, + "language": "typescript", + "label": "Per-environment prepared connection and session atoms", + "code": "import { connectionAtomRuntime } from \"../connection/runtime\";\nimport { appAtomRegistry } from \"../rpc/atomRegistry\";\n\nexport const environmentSession = createEnvironmentSessionAtoms(connectionAtomRuntime);\n\nconst EMPTY_PREPARED_CONNECTION_ATOM = Atom.make(Option.none()).pipe(\n Atom.withLabel(\"web-prepared-connection:empty\"),\n);\n\nexport function usePreparedConnection(environmentId: EnvironmentId | null) {\n return useAtomValue(\n environmentId === null\n ? EMPTY_PREPARED_CONNECTION_ATOM\n : environmentSession.preparedConnectionValueAtom(environmentId),\n );\n}\n\nexport function readPreparedConnection(environmentId: EnvironmentId) {\n return Option.getOrNull(\n appAtomRegistry.get(environmentSession.preparedConnectionValueAtom(environmentId)),\n );\n}\n\n/**\n * This client's authenticated session on one environment, as reported by that\n * environment's `/api/auth/session` endpoint. `data` stays populated across\n * SWR revalidations; `isPending` is only meaningful before the first resolve.\n */\nexport function useEnvironmentSessionState(environmentId: EnvironmentId) {\n const result = useAtomValue(environmentSession.sessionStateAtom(environmentId));\n return {\n data: Option.getOrNull(AsyncResult.value(result)),\n hasError: result._tag === \"Failure\",\n isPending: result.waiting,\n };", + "checksum": "cb1d832614b303c2cfbc77120eda1b5f34b9de30e2027c19db0b0e98dfae198e" + }, + "web-timeline-list-virtualization": { + "id": "web-timeline-list-virtualization", + "path": "apps/web/src/components/chat/MessagesTimeline.tsx", + "start": 570, + "end": 648, + "language": "tsx", + "label": "Keyed virtualized message timeline configuration", + "code": " if (rows.length === 0 && !isWorking) {\n if (hideEmptyPlaceholder) {\n return null;\n }\n return (\n
    \n

    Send a message to start the conversation.

    \n
    \n );\n }\n\n return (\n \n \n
    \n \n ref={listRef}\n data={rows}\n keyExtractor={keyExtractor}\n getItemType={getItemType}\n renderItem={renderItem}\n estimatedItemSize={90}\n initialScrollAtEnd\n {...(anchoredEndSpace ? { anchoredEndSpace } : {})}\n contentInsetEndAdjustment={contentInsetEndAdjustment}\n maintainScrollAtEnd={\n anchoredEndSpace || !liveFollowEnabled || disclosureToggleSettling\n ? false\n : TIMELINE_MAINTAIN_SCROLL_AT_END\n }\n maintainVisibleContentPosition={maintainVisibleContentPosition}\n onScroll={handleScroll}\n className={cn(\n \"scrollbar-gutter-both h-full min-h-0 overflow-x-hidden overscroll-y-contain px-3 [overflow-anchor:none] sm:px-5\",\n topFadeEnabled && \"topbar-scroll-fade\",\n )}\n ListHeaderComponent={\n loadEarlier !== null ? (\n \n ) : topFadeEnabled ? (\n TIMELINE_LIST_FADE_HEADER\n ) : (\n TIMELINE_LIST_HEADER\n )\n }\n ListFooterComponent={TIMELINE_LIST_FOOTER}\n />\n {\n onManualNavigation();\n void listRef.current?.scrollToIndex({\n index: item.rowIndex,\n animated: true,\n viewOffset: 24,\n });\n }}\n />\n
    \n
    \n
    \n );\n});\n\nfunction keyExtractor(item: MessagesTimelineRow) {\n return item.id;\n}\n\nfunction getItemType(item: MessagesTimelineRow) {\n return item.kind === \"message\" ? `message:${item.message.role}` : item.kind;\n}\n", + "checksum": "ad64d1e19d070fdd16b99a02269619f65b85df48b309607f10b58fb156a6832e" + }, + "web-timeline-row-structural-sharing": { + "id": "web-timeline-row-structural-sharing", + "path": "apps/web/src/components/chat/MessagesTimeline.tsx", + "start": 2095, + "end": 2113, + "language": "tsx", + "label": "Timeline row structural sharing for virtualized memo boundaries", + "code": "// so LegendList (and React) can skip re-rendering unchanged items.\n// ---------------------------------------------------------------------------\n\n/** Returns a structurally-shared copy of `rows`: for each row whose content\n * hasn't changed since last call, the previous object reference is reused. */\nfunction useStableRows(rows: MessagesTimelineRow[]): MessagesTimelineRow[] {\n const prevState = useRef({\n byId: new Map(),\n result: [],\n });\n\n return useMemo(() => {\n const nextState = computeStableMessagesTimelineRows(rows, prevState.current);\n prevState.current = nextState;\n return nextState.result;\n }, [rows]);\n}\n\n// ---------------------------------------------------------------------------", + "checksum": "74026e988767cb072249b769001abbf35b59542f6245e824e2fefdb2fbbe8ffc" + }, + "web-sidebar-row-locality": { + "id": "web-sidebar-row-locality", + "path": "apps/web/src/components/Sidebar.tsx", + "start": 2200, + "end": 2252, + "language": "tsx", + "label": "Sidebar streaming row locality and callback references", + "code": " SNOOZED_SHELF_EXPANDED_KEY,\n false,\n Schema.Boolean,\n );\n const toggleSnoozedShelf = useCallback(\n () => setSnoozedShelfExpanded((value) => !value),\n [setSnoozedShelfExpanded],\n );\n const visibleSnoozedThreads = useMemo(() => {\n if (snoozedShelfExpanded) return snoozedThreads;\n // The open thread must never vanish behind the collapsed shelf: a\n // snoozed thread reached by route (deep link, open before snoozing\n // elsewhere) keeps its row — with highlight and wake affordance — same\n // exception the settled tail's \"Show more\" makes.\n if (routeThreadKey === null) return [];\n const routeThread = snoozedThreads.find(\n (thread) =>\n scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)) === routeThreadKey,\n );\n return routeThread === undefined ? [] : [routeThread];\n }, [routeThreadKey, snoozedShelfExpanded, snoozedThreads]);\n\n const orderedThreads = useMemo(\n () => [...pinnedThreads, ...activeThreads, ...visibleSnoozedThreads, ...renderedSettledThreads],\n [pinnedThreads, activeThreads, visibleSnoozedThreads, renderedSettledThreads],\n );\n const orderedThreadKeys = useMemo(\n () =>\n orderedThreads.map((thread) =>\n scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)),\n ),\n [orderedThreads],\n );\n // Rows call back into the click handler without carrying the ordered list as\n // a prop — a fresh array identity per shell update would defeat every row's\n // memoization. The ref keeps shift-range-select working against the list as\n // rendered at click time.\n const orderedThreadKeysRef = useRef(orderedThreadKeys);\n orderedThreadKeysRef.current = orderedThreadKeys;\n const threadByKey = useMemo(\n () =>\n new Map(\n orderedThreads.map(\n (thread) =>\n [scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)), thread] as const,\n ),\n ),\n [orderedThreads],\n );\n // Handlers read these through refs: depending on per-update Map/Set\n // identities would give every row a fresh callback prop on each shell\n // event and defeat row memoization during streaming.\n const threadByKeyRef = useRef(threadByKey);", + "checksum": "0ca7fefcf227ef98a2738f7ce0001d6889c5b1e1e7a76701cdaab7ad1d3ed2ae" + }, + "web-client-tracing-export": { + "id": "web-client-tracing-export", + "path": "apps/web/src/observability/clientTracing.ts", + "start": 15, + "end": 96, + "language": "typescript", + "label": "Primary-environment OTLP client tracing lifecycle", + "code": "\nconst DEFAULT_EXPORT_INTERVAL_MS = 1_000;\nconst CLIENT_TRACING_RESOURCE = {\n serviceName: \"t3-web\",\n attributes: {\n \"service.runtime\": \"t3-web\",\n \"service.mode\": isElectron ? \"electron\" : \"browser\",\n \"service.version\": APP_VERSION,\n },\n} as const;\n\nconst delegateRuntimeLayer = Layer.mergeAll(\n primaryEnvironmentHttpLayer,\n OtlpExporter.layerFlusher,\n OtlpSerialization.layerJson,\n Layer.succeed(HttpClient.TracerDisabledWhen, () => true),\n);\n\nlet activeDelegate: Tracer.Tracer | null = null;\nlet activeRuntime: ManagedRuntime.ManagedRuntime | null = null;\nlet activeScope: Scope.Closeable | null = null;\nlet activeConfigKey: string | null = null;\nlet configurationGeneration = 0;\nlet pendingConfiguration = Promise.resolve();\n\nexport interface ClientTracingConfig {\n readonly exportIntervalMs?: number;\n}\n\nexport const ClientTracingLive = Layer.succeed(\n Tracer.Tracer,\n Tracer.make({\n span(options) {\n return activeDelegate?.span(options) ?? new Tracer.NativeSpan(options);\n },\n }),\n);\n\nexport function configureClientTracing(config: ClientTracingConfig = {}): Promise {\n if (config.exportIntervalMs === undefined && activeConfigKey !== null) {\n return pendingConfiguration;\n }\n pendingConfiguration = pendingConfiguration.finally(() => applyClientTracingConfig(config));\n return pendingConfiguration;\n}\n\nasync function applyClientTracingConfig(config: ClientTracingConfig): Promise {\n const otlpTracesUrl = resolvePrimaryEnvironmentHttpUrl(\"/api/observability/v1/traces\");\n const exportIntervalMs = Math.max(10, config.exportIntervalMs ?? DEFAULT_EXPORT_INTERVAL_MS);\n const nextConfigKey = `${otlpTracesUrl}|${exportIntervalMs}`;\n\n if (activeConfigKey === nextConfigKey && activeDelegate !== null) {\n return;\n }\n\n activeConfigKey = nextConfigKey;\n const generation = ++configurationGeneration;\n\n const previousRuntime = activeRuntime;\n const previousScope = activeScope;\n\n activeDelegate = null;\n activeRuntime = null;\n activeScope = null;\n\n await disposeTracerRuntime(previousRuntime, previousScope);\n\n const runtime = ManagedRuntime.make(delegateRuntimeLayer);\n const scope = runtime.runSync(Scope.make());\n\n const delegateResult = await settleAsyncResult(() =>\n runtime.runPromiseExit(\n Scope.provide(scope)(\n OtlpTracer.make({\n url: otlpTracesUrl,\n exportInterval: `${exportIntervalMs} millis`,\n resource: CLIENT_TRACING_RESOURCE,\n }),\n ),\n ),\n );\n if (delegateResult._tag === \"Failure\") {", + "checksum": "ea79ca0af49221763e5a8a63f3964a422be6f57b8bf234cea9115c51800954d5" + }, + "web-sidebar-optimistic-pinning": { + "id": "web-sidebar-optimistic-pinning", + "path": "apps/web/src/components/Sidebar.tsx", + "start": 2554, + "end": 2610, + "language": "tsx", + "label": "Optimistic pin-order override and canonical surrender rules", + "code": " // and holding it would launder a stale order into later drags.\n const pinnedDndSensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),\n );\n const [optimisticPinnedOrder, setOptimisticPinnedOrder] = useState<{\n readonly order: readonly string[];\n /** pinOrderKey per thread as of the drop — the baseline that tells a\n concurrent client's write apart from one of our own landing. */\n readonly keysAtDrop: ReadonlyMap;\n /** The keys this drop writes (one per planned assignment). The\n override holds until all of them appear in canonical state. */\n readonly assignedKeys: ReadonlyMap;\n } | null>(null);\n const orderedPinnedThreads = useMemo(() => {\n if (optimisticPinnedOrder === null) return pinnedThreads;\n return orderItemsByPreferredIds({\n items: pinnedThreads,\n preferredIds: optimisticPinnedOrder.order,\n getId: (thread) => scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)),\n });\n }, [optimisticPinnedOrder, pinnedThreads]);\n useEffect(() => {\n if (optimisticPinnedOrder === null) return;\n const canonical = pinnedThreads.filter((thread) =>\n reorderablePinnedKeys.has(scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id))),\n );\n const canonicalKeys = canonical.map((thread) =>\n scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)),\n );\n // The override represents one drop against one snapshot of the world.\n // Release it when the world moves on: membership changed (pin/unpin/\n // snooze/wake — the override can't say where members it never saw\n // belong), a key changed to something we did NOT write (a concurrent\n // client's reorder that must win), every key we wrote has landed, or\n // canonical already matches. Releasing on the FIRST landed key instead\n // of the last exposes the half-written order mid-materialization and\n // the block visibly reshuffles once per write.\n const membershipChanged =\n canonicalKeys.length !== optimisticPinnedOrder.order.length ||\n canonicalKeys.some((key) => !optimisticPinnedOrder.order.includes(key));\n const foreignKeyLanded = canonical.some((thread, index) => {\n const threadKey = canonicalKeys[index]!;\n const currentKey = thread.pinOrderKey ?? null;\n if (currentKey === optimisticPinnedOrder.keysAtDrop.get(threadKey)) return false;\n return currentKey !== optimisticPinnedOrder.assignedKeys.get(threadKey);\n });\n const currentKeyByThreadKey = new Map(\n canonical.map((thread, index) => [canonicalKeys[index]!, thread.pinOrderKey ?? null]),\n );\n const allAssignmentsLanded = [...optimisticPinnedOrder.assignedKeys].every(\n ([threadKey, orderKey]) => currentKeyByThreadKey.get(threadKey) === orderKey,\n );\n const orderConfirmed =\n !membershipChanged &&\n canonicalKeys.every((key, index) => key === optimisticPinnedOrder.order[index]);\n if (membershipChanged || foreignKeyLanded || allAssignmentsLanded || orderConfirmed) {\n setOptimisticPinnedOrder(null);", + "checksum": "587d2e08f3d5f4a8193054fcd9c8afa66b3c80d57456718f2adcdee4ffa71836" + }, + "mobile-app-root-composition": { + "id": "mobile-app-root-composition", + "path": "apps/mobile/src/App.tsx", + "start": 61, + "end": 106, + "language": "tsx", + "label": "Mobile root Atom, provider, navigation, and native host composition", + "code": "export default function App() {\n return (\n \n \n \n \n \n \n \n );\n}\n\nfunction AppContent() {\n const { themeAppearance } = useAppearancePreferences();\n const statusBarBg = useThemeColor(\"--color-status-bar\");\n const navigationTheme = useMobileNavigationTheme(themeAppearance);\n\n return (\n <>\n \n \n \n \n \n {/* The navigation theme drives the NATIVE header appearance: native-stack\n forwards `dark` as the nav bar's overrideUserInterfaceStyle. Without\n this, React Navigation defaults to its light theme and every native\n header (glass buttons, title, materials) is forced light even when\n the system is in dark mode. */}\n {/* Blur target for Android dropdown backdrops — see appBlurTarget.ts. */}\n \n \n \n \n \n \n {/* Anchored-menu overlays render here — in-window, so the\n keyboard stays up while a dropdown is open. */}\n \n \n \n ", + "checksum": "46115b33d72272b987a9b97658d848d7e5fd73e991f885c285a6c2ff369725fd" + }, + "mobile-connection-runtime-layer": { + "id": "mobile-connection-runtime-layer", + "path": "apps/mobile/src/connection/runtime.ts", + "start": 1, + "end": 45, + "language": "typescript", + "label": "Shared connection and snapshot layers with mobile platform services", + "code": "import { Connection } from \"@t3tools/client-runtime/connection\";\nimport { shellSnapshotLoaderLayer } from \"@t3tools/client-runtime/state/shell\";\nimport { threadSnapshotLoaderLayer } from \"@t3tools/client-runtime/state/threads\";\nimport * as Layer from \"effect/Layer\";\nimport { Atom } from \"effect/unstable/reactivity\";\n\nimport { runtimeContextLayer } from \"../lib/runtime\";\nimport {\n mobileBackgroundActivityObserverLayer,\n mobileBackgroundActivityReporterLayer,\n} from \"./background-activity\";\nimport { connectionPlatformLayer } from \"./platform\";\n\nconst providedConnectionPlatformLayer = connectionPlatformLayer.pipe(\n Layer.provide(runtimeContextLayer),\n);\n\nconst snapshotLoaderLayer = Layer.merge(threadSnapshotLoaderLayer, shellSnapshotLoaderLayer);\n\ntype ConnectionLayerSource =\n | typeof Connection.layer\n | typeof snapshotLoaderLayer\n | typeof runtimeContextLayer\n | typeof connectionPlatformLayer\n | typeof mobileBackgroundActivityObserverLayer\n | typeof mobileBackgroundActivityReporterLayer;\n\nconst providedClientConnectionLayer = Layer.merge(Connection.layer, snapshotLoaderLayer).pipe(\n Layer.provideMerge(\n Layer.mergeAll(\n runtimeContextLayer,\n providedConnectionPlatformLayer,\n mobileBackgroundActivityObserverLayer,\n ),\n ),\n);\n\nconst connectionLayer = mobileBackgroundActivityReporterLayer.pipe(\n Layer.provideMerge(providedClientConnectionLayer),\n);\n\nexport const connectionAtomRuntime: Atom.AtomRuntime<\n Layer.Success,\n Layer.Error\n> = Atom.runtime(connectionLayer);", + "checksum": "b65580b503a79da712a1398f7ef6988f434ec21193c7223eca5edbf597857db4" + }, + "mobile-persistence-schema": { + "id": "mobile-persistence-schema", + "path": "apps/mobile/src/persistence/mobile-database.ts", + "start": 242, + "end": 275, + "language": "typescript", + "label": "SQLite client cache and preference schema with versioned migration", + "code": " yield* Effect.tryPromise({\n try: async () => {\n await database.execAsync(\"PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON;\");\n const schema = await database.getFirstAsync<{ readonly user_version: number }>(\n \"PRAGMA user_version\",\n );\n await database.withExclusiveTransactionAsync(async (transaction) => {\n await transaction.execAsync(`\n CREATE TABLE IF NOT EXISTS client_cache (\n environment_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n cache_key TEXT NOT NULL,\n schema_version INTEGER NOT NULL,\n payload TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (environment_id, kind, cache_key)\n ) WITHOUT ROWID;\n\n CREATE INDEX IF NOT EXISTS client_cache_environment_updated\n ON client_cache (environment_id, updated_at DESC);\n\n CREATE TABLE IF NOT EXISTS client_preferences (\n singleton INTEGER PRIMARY KEY NOT NULL CHECK (singleton = 1),\n payload TEXT NOT NULL,\n updated_at INTEGER NOT NULL\n );\n `);\n });\n if ((schema?.user_version ?? 0) < DATABASE_SCHEMA_VERSION) {\n const migrated = await migrateLegacyFileCaches(database);\n if (migrated) {\n await database.execAsync(`PRAGMA user_version = ${DATABASE_SCHEMA_VERSION};`);\n }\n }", + "checksum": "4c4f4137e909027a14ac1ec6e1724cfb765961790354b87747351df46910ecb0" + }, + "mobile-draft-update-flush": { + "id": "mobile-draft-update-flush", + "path": "apps/mobile/src/state/use-composer-drafts.ts", + "start": 212, + "end": 229, + "language": "typescript", + "label": "Draft persistence flush before JavaScript runtime teardown", + "code": "/**\n * Lands any debounced or in-flight draft write before the JS runtime is torn\n * down (app update restart), so the freshest draft state survives it. A write\n * failure propagates so the caller can decide whether the restart may proceed.\n */\nexport async function flushComposerDrafts(): Promise {\n // An edit during an awaited write schedules another debounced write, so\n // keep landing snapshots until no debounce is pending after a queue drain.\n do {\n while (persistTimer !== null) {\n clearTimeout(persistTimer);\n persistTimer = null;\n await persistenceQueue.run(() =>\n writePersistedComposerDrafts(appAtomRegistry.get(composerDraftsAtom)),\n );\n }\n await persistenceQueue.run(() => Promise.resolve());\n } while (persistTimer !== null);", + "checksum": "eae8cd0dee12f66549b90f8f01a1eca248189e6b8a1c0c5d7af1bc9ea281c576" + }, + "mobile-outbox-optimistic-durability": { + "id": "mobile-outbox-optimistic-durability", + "path": "apps/mobile/src/state/thread-outbox-manager.ts", + "start": 91, + "end": 124, + "language": "typescript", + "label": "Optimistic enqueue, durable rollback, and pre-delivery confirmation", + "code": " // The queued atom drives the composer's immediate \"queued\" feedback, so it\n // is published synchronously; the durable write happens behind it and rolls\n // the message back out if it fails (durability only matters for crash\n // recovery, not for the in-session queue).\n const enqueue = (message: QueuedThreadMessage): Promise => {\n setMessages([\n ...currentMessages().filter((candidate) => candidate.messageId !== message.messageId),\n message,\n ]);\n return serialize(async () => {\n try {\n await options.storage.write(message);\n } catch (cause) {\n // Roll back by reference, not messageId: a retry enqueue with the same\n // id may have optimistically replaced this attempt while the write was\n // in flight, and its entry must survive this attempt's failure.\n setMessages(currentMessages().filter((candidate) => candidate !== message));\n throw new ThreadOutboxManagerError({\n operation: \"enqueue\",\n environmentId: message.environmentId,\n threadId: message.threadId,\n messageId: message.messageId,\n cause,\n });\n }\n });\n };\n\n // Resolves once all pending mutations (including any in-flight enqueue\n // write) have settled, reporting whether the message is still queued. The\n // drain awaits this before dispatching so a message whose durable write\n // later fails can never have been delivered first.\n const confirmQueued = (message: QueuedThreadMessage): Promise =>\n serialize(async () => currentMessages().some((candidate) => candidate === message));", + "checksum": "616baa8c3ce65855265d73b8db622400fa95ca5b49951b6aa112a214a55dc21c" + }, + "mobile-outbox-delivery-policy": { + "id": "mobile-outbox-delivery-policy", + "path": "apps/mobile/src/state/thread-outbox-model.ts", + "start": 145, + "end": 226, + "language": "typescript", + "label": "Outbox existence guards, capped backoff, and failure classification", + "code": "export function threadOutboxRetryDelayMs(attempt: number): number {\n return Math.min(1_000 * 2 ** Math.max(0, attempt - 1), THREAD_OUTBOX_MAX_RETRY_DELAY_MS);\n}\n\nexport type ThreadOutboxDeliveryAction = \"wait\" | \"remove\" | \"send\";\n\nexport function resolveThreadOutboxDeliveryAction(input: {\n readonly isCreation: boolean;\n readonly threadExists: boolean;\n readonly shellStatus: EnvironmentShellStatus;\n readonly environmentConnected: boolean;\n readonly threadBusy: boolean;\n}): ThreadOutboxDeliveryAction {\n if (input.isCreation) {\n // A pending task creates its thread on delivery. If the thread already\n // exists the creation command went through and only cleanup remains.\n if (input.threadExists) {\n return \"remove\";\n }\n // Wait for the shell to be live before sending: until the thread list has\n // synchronized, a previously delivered creation whose cleanup failed would\n // look missing and get re-issued, duplicating the thread.\n return input.environmentConnected && input.shellStatus === \"live\" ? \"send\" : \"wait\";\n }\n if (!input.threadExists) {\n return input.shellStatus === \"live\" ? \"remove\" : \"wait\";\n }\n return input.environmentConnected ? \"send\" : \"wait\";\n}\n\n/**\n * A queued creation can only be dispatched once its payload would pass server\n * validation; incomplete payloads stay pending until the user edits them.\n */\nexport function isQueuedThreadCreationSendable(message: QueuedThreadMessage): boolean {\n if (!message.creation) {\n return false;\n }\n if (message.text.trim().length === 0 || message.modelSelection === undefined) {\n return false;\n }\n return message.creation.workspaceMode !== \"worktree\" || Boolean(message.creation.branch);\n}\n\nfunction errorMessage(error: unknown): string | null {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n return typeof error.message === \"string\" ? error.message : null;\n }\n return typeof error === \"string\" ? error : null;\n}\n\nexport function shouldRetryThreadOutboxDelivery(error: unknown): boolean {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"_tag\" in error &&\n error._tag === \"ConnectionTransientError\"\n ) {\n return true;\n }\n return isTransportConnectionErrorMessage(errorMessage(error));\n}\n\nexport type ThreadOutboxCommandStage = \"settings-sync\" | \"start-turn\";\nexport type ThreadOutboxFailureAction = \"retry\" | \"discard\";\n\nexport function resolveThreadOutboxFailureAction(input: {\n readonly stage: ThreadOutboxCommandStage;\n readonly error: unknown;\n readonly interrupted: boolean;\n}): ThreadOutboxFailureAction {\n if (\n input.stage === \"settings-sync\" ||\n input.interrupted ||\n shouldRetryThreadOutboxDelivery(input.error)\n ) {\n return \"retry\";\n }\n return \"discard\";", + "checksum": "d2969b0b428827e9c62ee69aaa4353ae90a097d523872d145dc0650edd68d6cf" + }, + "mobile-share-commit-boundary": { + "id": "mobile-share-commit-boundary", + "path": "apps/mobile/src/features/sharing/incoming-share-inbox.ts", + "start": 46, + "end": 124, + "language": "typescript", + "label": "Durable share inbox write before native handoff acknowledgement", + "code": "/**\n * Serializes every durable inbox mutation. This prevents a stale storage load\n * or a foreground refresh from restoring an item after it has been consumed.\n */\nexport class IncomingShareInbox {\n private readonly operations = new SerializedAsyncQueue();\n\n constructor(private readonly dependencies: IncomingShareInboxDependencies) {}\n\n private runExclusive(operation: () => Promise): Promise {\n return this.operations.run(operation);\n }\n\n private clearNativePayloads(): void {\n try {\n this.dependencies.clearPayloads();\n } catch (error) {\n this.dependencies.onClearError?.(error);\n }\n }\n\n private async cleanup(operation: () => Promise): Promise {\n try {\n await operation();\n } catch (error) {\n this.dependencies.onCleanupError?.(error);\n }\n }\n\n refresh(options: { readonly ingestNative: boolean }): Promise> {\n return this.runExclusive(async () => {\n const loaded = await this.dependencies.loadDrafts();\n const persisted = sortAndDedupeIncomingShares(loaded);\n if (!options.ingestNative) {\n return persisted;\n }\n\n const payloads = this.dependencies.getPayloads();\n if (payloads.length === 0) {\n return persisted;\n }\n\n // A share extension payload remains available until the containing app\n // acknowledges it. Use a content-derived id so a crash after the durable\n // write but before acknowledgement reuses the same inbox item.\n const shareId = await this.dependencies.idForPayloads(payloads);\n if (loaded.some((draft) => draft.id === shareId)) {\n if (this.dependencies.cleanupReplayedPayloads) {\n await this.cleanup(() => this.dependencies.cleanupReplayedPayloads!(payloads));\n }\n this.clearNativePayloads();\n return persisted;\n }\n\n const built = await this.dependencies.buildDraft({\n payloads,\n id: shareId,\n createdAt: this.dependencies.now(),\n });\n const { draft } = built;\n if (!hasIncomingShareContent(draft)) {\n // Unsupported native payloads cannot become actionable on retry and\n // would otherwise reopen the project picker on every foreground.\n await this.cleanup(built.cleanup);\n this.clearNativePayloads();\n throw new Error(\n draft.warnings[0] ?? \"The shared content is not supported by the composer.\",\n );\n }\n\n // The durable inbox write is the transaction boundary. Never clear the\n // native handoff first: a process termination must leave one recoverable\n // copy on one side of the boundary.\n await this.dependencies.writeDraft(draft);\n await this.cleanup(built.cleanup);\n this.clearNativePayloads();\n return sortAndDedupeIncomingShares([draft, ...persisted]);\n });\n }", + "checksum": "0677f4b5f578d272ee74ec62dbb82f10bfbf9f0a1e7fb08a7aebd371b20e891e" + }, + "mobile-native-surface-probe": { + "id": "mobile-native-surface-probe", + "path": "apps/mobile/src/features/terminal/nativeTerminalModule.ts", + "start": 48, + "end": 100, + "language": "typescript", + "label": "Optional native terminal resolution and compiled revision probe", + "code": "export function resolveNativeTerminalSurfaceView(): ComponentType | null {\n if (cachedNativeTerminalSurfaceView) {\n return cachedNativeTerminalSurfaceView;\n }\n\n if (nativeTerminalSurfaceViewResolutionFailed) {\n return null;\n }\n\n if (getExpoViewConfig(NATIVE_TERMINAL_MODULE_NAME) == null) {\n return null;\n }\n\n try {\n cachedNativeTerminalSurfaceView = requireNativeView(\n NATIVE_TERMINAL_MODULE_NAME,\n );\n } catch (cause) {\n nativeTerminalSurfaceViewResolutionFailed = true;\n console.error(\n new NativeViewResolutionError({\n nativeModuleName: NATIVE_TERMINAL_MODULE_NAME,\n cause,\n }),\n );\n return null;\n }\n\n return cachedNativeTerminalSurfaceView ?? null;\n}\n\n/**\n * Revision of the native hardware-keyboard handling compiled into the installed binary,\n * or `null` when the binary predates the revision constant (or the module is missing).\n * Used in terminal debug logs to detect stale native builds.\n */\nexport function getNativeTerminalHardwareKeyRevision(): number | null {\n try {\n if (typeof requireOptionalNativeModule !== \"function\") {\n return null;\n }\n const module = requireOptionalNativeModule<{ readonly hardwareKeyRevision?: number }>(\n NATIVE_TERMINAL_MODULE_NAME,\n );\n return module?.hardwareKeyRevision ?? null;\n } catch {\n return null;\n }\n}\n\nexport function hasNativeTerminalSurface() {\n return resolveNativeTerminalSurfaceView() !== null;\n}", + "checksum": "daf96c0c42f44f5c8c887398b2a5433dad5ca64c2e1095a57da203bcce82c4d6" + }, + "mobile-update-restart-guard": { + "id": "mobile-update-restart-guard", + "path": "apps/mobile/src/features/updates/app-updates.ts", + "start": 417, + "end": 480, + "language": "typescript", + "label": "Deferred OTA flush and foreground-handoff safety gate", + "code": "async function applyDeferredAppUpdateInstall(\n client: AppUpdateClient,\n environment: AppUpdateEnvironment,\n deferral: AppUpdateDeferral,\n): Promise {\n if (!deferral.pendingInstall || deferral.installInProgress) return;\n deferral.installInProgress = true;\n const flushed = await settlePromise(() => environment.flushPendingWrites());\n const safe = await settlePromise(() => environment.isSafeToRestartInBackground());\n if (flushed._tag === \"Failure\" || safe._tag !== \"Success\" || !safe.value) {\n if (flushed._tag === \"Failure\") {\n // Nothing is lost yet: keep the state-bearing runtime alive and retry\n // the flush at the next backgrounding instead of restarting over it.\n reportUpdateFailure(flushed, \"Could not save pending state.\", undefined);\n }\n deferral.installInProgress = false;\n // This attempt already ran in the current background session; retrying\n // before a fresh transition would just loop over the same failure.\n scheduleDeferredAppUpdateInstall(client, environment, deferral, false);\n return;\n }\n const reloaded = await settlePromise(() => client.reloadAsync());\n if (reloaded._tag === \"Failure\") {\n reportUpdateFailure(reloaded, \"Downloaded, but could not restart the app.\", undefined);\n deferral.installInProgress = false;\n // Let later checks re-arm the install; the downloaded update still\n // applies at the next cold start regardless.\n deferral.pendingInstall = false;\n }\n}\n\nasync function defaultConfirmInstallNow(): Promise {\n const { Alert } = await import(\"react-native\");\n return new Promise((resolve) => {\n Alert.alert(\n \"Update ready\",\n \"A new version has been downloaded and installs automatically the next time you leave the app. Install it now instead?\",\n [\n { onPress: () => resolve(false), style: \"cancel\", text: \"Later\" },\n { onPress: () => resolve(true), text: \"Install Now\" },\n ],\n { cancelable: true, onDismiss: () => resolve(false) },\n );\n });\n}\n\nasync function defaultFlushPendingWrites(): Promise {\n // Attempt every flush before surfacing the first failure, so one broken\n // store cannot keep the others from landing.\n const results = await Promise.allSettled([\n import(\"../../state/use-composer-drafts\").then((drafts) => drafts.flushComposerDrafts()),\n import(\"../../state/thread-outbox\").then((outbox) => outbox.flushThreadOutbox()),\n ]);\n const failed = results.find(\n (result): result is PromiseRejectedResult => result.status === \"rejected\",\n );\n if (failed) throw failed.reason;\n}\n\nasync function defaultIsSafeToRestartInBackground(): Promise {\n const { isForegroundHandoffActive } = await import(\"../../lib/foreground-handoff\");\n if (isForegroundHandoffActive()) return false;\n const { AppState } = await import(\"react-native\");\n return AppState.currentState === \"background\";", + "checksum": "c7202351a95153093f1dd5607987e399683888e4ca03628c4aef7bc2afd51cc2" + }, + "desktop-preload-bridge": { + "id": "desktop-preload-bridge", + "path": "apps/desktop/src/preload.ts", + "start": 30, + "end": 103, + "language": "typescript", + "label": "Curated renderer bridge for local, SSH, exposure, WSL, and file operations", + "code": "contextBridge.exposeInMainWorld(\"desktopBridge\", {\n getAppBranding: () => {\n const result = ipcRenderer.sendSync(IpcChannels.GET_APP_BRANDING_CHANNEL);\n if (typeof result !== \"object\" || result === null) {\n return null;\n }\n return result as ReturnType;\n },\n getSystemLocale: () => {\n const result = ipcRenderer.sendSync(IpcChannels.GET_SYSTEM_LOCALE_CHANNEL);\n return typeof result === \"string\" ? result : null;\n },\n getLocalEnvironmentBootstraps: () => {\n const result = ipcRenderer.sendSync(IpcChannels.GET_LOCAL_ENVIRONMENT_BOOTSTRAPS_CHANNEL);\n if (!Array.isArray(result)) {\n return [];\n }\n return result as ReturnType;\n },\n getLocalEnvironmentBearerToken: () =>\n ipcRenderer.invoke(IpcChannels.GET_LOCAL_ENVIRONMENT_BEARER_TOKEN_CHANNEL),\n getClientSettings: () => ipcRenderer.invoke(IpcChannels.GET_CLIENT_SETTINGS_CHANNEL),\n setClientSettings: (settings) =>\n ipcRenderer.invoke(IpcChannels.SET_CLIENT_SETTINGS_CHANNEL, settings),\n getConnectionCatalog: () => ipcRenderer.invoke(IpcChannels.GET_CONNECTION_CATALOG_CHANNEL),\n setConnectionCatalog: (catalog) =>\n ipcRenderer.invoke(IpcChannels.SET_CONNECTION_CATALOG_CHANNEL, catalog),\n clearConnectionCatalog: () => ipcRenderer.invoke(IpcChannels.CLEAR_CONNECTION_CATALOG_CHANNEL),\n discoverSshHosts: () => ipcRenderer.invoke(IpcChannels.DISCOVER_SSH_HOSTS_CHANNEL),\n ensureSshEnvironment: async (target, options) =>\n unwrapEnsureSshEnvironmentResult(\n await ipcRenderer.invoke(IpcChannels.ENSURE_SSH_ENVIRONMENT_CHANNEL, {\n target,\n ...(options === undefined ? {} : { options }),\n }),\n ),\n disconnectSshEnvironment: (target) =>\n ipcRenderer.invoke(IpcChannels.DISCONNECT_SSH_ENVIRONMENT_CHANNEL, target),\n fetchSshEnvironmentDescriptor: (httpBaseUrl) =>\n ipcRenderer.invoke(IpcChannels.FETCH_SSH_ENVIRONMENT_DESCRIPTOR_CHANNEL, { httpBaseUrl }),\n bootstrapSshBearerSession: (httpBaseUrl, credential) =>\n ipcRenderer.invoke(IpcChannels.BOOTSTRAP_SSH_BEARER_SESSION_CHANNEL, {\n httpBaseUrl,\n credential,\n }),\n fetchSshSessionState: (httpBaseUrl, bearerToken) =>\n ipcRenderer.invoke(IpcChannels.FETCH_SSH_SESSION_STATE_CHANNEL, { httpBaseUrl, bearerToken }),\n issueSshWebSocketTicket: (httpBaseUrl, bearerToken) =>\n ipcRenderer.invoke(IpcChannels.ISSUE_SSH_WEBSOCKET_TOKEN_CHANNEL, { httpBaseUrl, bearerToken }),\n onSshPasswordPrompt: (listener) => {\n const wrappedListener = (_event: Electron.IpcRendererEvent, request: unknown) => {\n if (typeof request !== \"object\" || request === null) return;\n listener(request as Parameters[0]);\n };\n\n ipcRenderer.on(IpcChannels.SSH_PASSWORD_PROMPT_CHANNEL, wrappedListener);\n return () => {\n ipcRenderer.removeListener(IpcChannels.SSH_PASSWORD_PROMPT_CHANNEL, wrappedListener);\n };\n },\n resolveSshPasswordPrompt: (requestId, password) =>\n ipcRenderer.invoke(IpcChannels.RESOLVE_SSH_PASSWORD_PROMPT_CHANNEL, { requestId, password }),\n getServerExposureState: () => ipcRenderer.invoke(IpcChannels.GET_SERVER_EXPOSURE_STATE_CHANNEL),\n setServerExposureMode: (mode) =>\n ipcRenderer.invoke(IpcChannels.SET_SERVER_EXPOSURE_MODE_CHANNEL, mode),\n setTailscaleServeEnabled: (input) =>\n ipcRenderer.invoke(IpcChannels.SET_TAILSCALE_SERVE_ENABLED_CHANNEL, input),\n getAdvertisedEndpoints: () => ipcRenderer.invoke(IpcChannels.GET_ADVERTISED_ENDPOINTS_CHANNEL),\n getWslState: () => ipcRenderer.invoke(IpcChannels.GET_WSL_STATE_CHANNEL),\n setWslBackendEnabled: (enabled) =>\n ipcRenderer.invoke(IpcChannels.SET_WSL_BACKEND_ENABLED_CHANNEL, enabled),\n setWslDistro: (distro) => ipcRenderer.invoke(IpcChannels.SET_WSL_DISTRO_CHANNEL, distro),\n setWslOnly: (enabled) => ipcRenderer.invoke(IpcChannels.SET_WSL_ONLY_CHANNEL, enabled),\n pickFolder: (options) => ipcRenderer.invoke(IpcChannels.PICK_FOLDER_CHANNEL, options),", + "checksum": "f1c239b62a4b38550da29b44ca8086edd3b2f76df4483787b6628674fe980daf" + }, + "desktop-bootstrap-order": { + "id": "desktop-bootstrap-order", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 142, + "end": 218, + "language": "typescript", + "label": "Endpoint selection, desktop protocol, IPC, primary start, and parallel WSL reconciliation", + "code": "const bootstrap = Effect.gen(function* () {\n const pool = yield* DesktopBackendPool.DesktopBackendPool;\n const primaryBackend = yield* pool.primary;\n const state = yield* DesktopState.DesktopState;\n const environment = yield* DesktopEnvironment.DesktopEnvironment;\n const desktopSettings = yield* DesktopAppSettings.DesktopAppSettings;\n const serverExposure = yield* DesktopServerExposure.DesktopServerExposure;\n const wslBackend = yield* DesktopWslBackend.DesktopWslBackend;\n const desktopWindow = yield* DesktopWindow.DesktopWindow;\n yield* logBootstrapInfo(\"bootstrap start\");\n\n if (environment.isDevelopment && Option.isNone(environment.configuredBackendPort)) {\n return yield* new DesktopDevelopmentBackendPortRequiredError();\n }\n\n const backendPortSelection = yield* resolveDesktopBackendPort(environment.configuredBackendPort);\n const backendPort = backendPortSelection.port;\n yield* logBootstrapInfo(\n backendPortSelection.selectedByScan\n ? \"selected backend port via sequential scan\"\n : \"using configured backend port\",\n {\n port: backendPort,\n ...(backendPortSelection.selectedByScan ? { startPort: DEFAULT_DESKTOP_BACKEND_PORT } : {}),\n },\n );\n\n const settings = yield* desktopSettings.get;\n if (settings.serverExposureMode !== environment.defaultDesktopSettings.serverExposureMode) {\n yield* logBootstrapInfo(\"bootstrap restoring persisted server exposure mode\", {\n mode: settings.serverExposureMode,\n });\n }\n const serverExposureState = yield* serverExposure.configureFromSettings({ port: backendPort });\n const backendConfig = yield* serverExposure.backendConfig;\n const electronProtocol = yield* ElectronProtocol.ElectronProtocol;\n const rendererTarget = environment.isDevelopment\n ? Option.getOrThrow(environment.devServerUrl)\n : backendConfig.httpBaseUrl;\n yield* electronProtocol.registerDesktopProtocol({\n scheme: ElectronProtocol.getDesktopScheme(environment.isDevelopment),\n targetOrigin: rendererTarget,\n backendOrigin: backendConfig.httpBaseUrl,\n clerkFrontendApiHostname: DesktopClerk.desktopClerkFrontendApiHostname,\n });\n yield* logBootstrapInfo(\"bootstrap resolved backend endpoint\", {\n baseUrl: backendConfig.httpBaseUrl.href,\n });\n if (serverExposureState.endpointUrl) {\n yield* logBootstrapInfo(\"bootstrap enabled network access\", {\n endpointUrl: serverExposureState.endpointUrl,\n });\n } else if (settings.serverExposureMode === \"network-accessible\") {\n yield* logBootstrapWarning(\n \"bootstrap fell back to local-only because no advertised network host was available\",\n );\n }\n\n yield* installDesktopIpcHandlers();\n yield* logBootstrapInfo(\"bootstrap ipc handlers registered\");\n\n if (!(yield* Ref.get(state.quitting))) {\n // In wsl-only mode the renderer is served by the WSL backend, which can be\n // slow to cold-boot — show a \"Connecting to WSL\" splash immediately so the\n // app feels responsive instead of presenting no window until WSL is ready.\n // (Dual mode opens fast off the Windows primary, so no splash there.)\n if (settings.wslOnly === true && settings.wslBackendEnabled === true) {\n yield* desktopWindow.showConnectingSplash;\n }\n yield* primaryBackend.start;\n yield* logBootstrapInfo(\"bootstrap backend start requested\");\n // Bring up the WSL backend if the user previously enabled it. The\n // primary is already starting; reconcile fires off the WSL register\n // in parallel rather than blocking primary readiness on a possibly\n // slow first wsl.exe spawn.\n yield* Effect.forkScoped(wslBackend.reconcile);\n }", + "checksum": "3382a448d70b84c155daa8b98ea9f42a42702152d451cb49be7ba0608c948342" + }, + "desktop-primary-platform-choice": { + "id": "desktop-primary-platform-choice", + "path": "apps/desktop/src/backend/DesktopBackendConfiguration.ts", + "start": 689, + "end": 728, + "language": "typescript", + "label": "Host-local primary label with the Windows-only WSL override", + "code": " // Single source of truth for what the primary actually runs as. Both\n // the start-config dispatch and the renderer-facing label derive from\n // this, so they can't disagree — e.g. the label reading \"WSL\" while the\n // config silently fell back to Windows because WSL is unavailable.\n // Dispatch happens at resolve time so toggling wsl-only between restarts\n // is picked up on the next start cycle (the pool's primary instance is\n // created once at layer init, but configResolve fires on each restart).\n const describePrimary = Effect.gen(function* () {\n const persistedSettings = yield* settings.get;\n const wslRequested = persistedSettings.wslOnly && persistedSettings.wslBackendEnabled;\n // Only honor wsl-only when WSL is actually usable. If the user\n // persisted wsl-only but WSL has since become unavailable (wsl.exe\n // removed, no distro), fall back to the Windows primary instead of\n // looping forever on preflight failures: the Connections backend\n // control is hidden while WSL is unavailable, so a stuck WSL primary\n // would otherwise leave no in-app way back to Windows.\n const useWsl = wslRequested && (yield* wslEnvironment.isAvailable);\n return { useWsl, wslRequested, distro: persistedSettings.wslDistro };\n });\n\n return DesktopBackendConfiguration.of({\n resolvePrimary: Effect.gen(function* () {\n const { useWsl, wslRequested } = yield* describePrimary;\n if (useWsl) {\n return yield* buildWslPrimaryConfig;\n }\n if (wslRequested) {\n yield* Effect.logWarning(\n \"WSL-only backend requested but WSL is unavailable; starting the Windows primary instead.\",\n );\n }\n return yield* buildWindowsPrimaryConfig;\n }).pipe(Effect.withSpan(\"desktop.backendConfiguration.resolvePrimary\")),\n resolvePrimaryLabel: Effect.gen(function* () {\n const { useWsl, distro } = yield* describePrimary;\n if (!useWsl) {\n return environment.platform === \"win32\" ? \"Windows\" : \"Local environment\";\n }\n return distro ? `WSL (${distro})` : \"WSL\";\n }).pipe(Effect.withSpan(\"desktop.backendConfiguration.resolvePrimaryLabel\")),", + "checksum": "58261db624128a02030dd25fb009fc7f141e0d8e67cf9b57cfab3735e468550d" + }, + "desktop-pool-scope-lifecycle": { + "id": "desktop-pool-scope-lifecycle", + "path": "apps/desktop/src/backend/DesktopBackendPool.ts", + "start": 327, + "end": 419, + "language": "typescript", + "label": "Per-instance child scopes and primary-protected unregister lifecycle", + "code": " return Effect.fail(\n new DesktopBackendPoolInstanceAlreadyRegisteredError({ id: spec.id }),\n );\n }\n if (existing?._tag === \"Closing\") {\n return Effect.succeed([\n { _tag: \"Wait\", done: existing.done } as const,\n current,\n ] as const);\n }\n return Effect.gen(function* () {\n // Provide the captured factory services first, then the child scope\n // last so instance finalizers are owned by the unregisterable scope.\n const instanceScope = yield* Scope.fork(layerScope, \"sequential\");\n const instance = yield* DesktopBackendManager.makeBackendInstance(spec).pipe(\n Effect.provide(factoryContext),\n Scope.provide(instanceScope),\n );\n const next = new Map(current);\n next.set(spec.id, {\n _tag: \"Active\",\n instance,\n scope: Option.some(instanceScope),\n });\n return [\n { _tag: \"Registered\", instance } as const,\n next as ReadonlyMap,\n ] as const;\n });\n },\n ).pipe(\n Effect.flatMap((result) =>\n result._tag === \"Registered\"\n ? Effect.succeed(result.instance)\n : Deferred.await(result.done).pipe(Effect.andThen(register(spec))),\n ),\n ),\n );\n\n const unregister: DesktopBackendPool[\"Service\"][\"unregister\"] = (id) =>\n Effect.gen(function* () {\n if (id === DesktopBackendManager.PRIMARY_INSTANCE_ID) {\n return yield* new DesktopBackendPoolCannotUnregisterPrimaryError();\n }\n const done = yield* Deferred.make();\n const action = yield* SynchronizedRef.modifyEffect(\n instancesRef,\n (\n current,\n ): Effect.Effect<\n readonly [UnregisterAction, ReadonlyMap]\n > => {\n const entry = current.get(id);\n if (entry === undefined) {\n return Effect.succeed([{ _tag: \"Absent\" } as const, current] as const);\n }\n if (entry._tag === \"Closing\") {\n return Effect.succeed([\n { _tag: \"Wait\", done: entry.done } as const,\n current,\n ] as const);\n }\n const next = new Map(current);\n next.set(id, { _tag: \"Closing\", done });\n return Effect.succeed([\n { _tag: \"Close\", entry } as const,\n next as ReadonlyMap,\n ] as const);\n },\n );\n\n if (action._tag === \"Absent\") return;\n if (action._tag === \"Wait\") {\n yield* Deferred.await(action.done);\n return;\n }\n\n const finish = SynchronizedRef.modifyEffect(instancesRef, (current) => {\n const closing = current.get(id);\n if (closing?._tag !== \"Closing\" || closing.done !== done) {\n return Effect.succeed([undefined, current] as const);\n }\n const next = new Map(current);\n next.delete(id);\n return Effect.succeed([\n undefined,\n next as ReadonlyMap,\n ] as const);\n }).pipe(Effect.andThen(Deferred.succeed(done, undefined)), Effect.asVoid);\n yield* Option.match(action.entry.scope, {\n onNone: () => Effect.void,\n onSome: (scope) => Scope.close(scope, Exit.void).pipe(Effect.ignore),\n }).pipe(Effect.ensuring(finish));", + "checksum": "6cc62e74d59a260508a4457eaed647f2bcf1ff9b77a41fd4d41276af7f22aab0" + }, + "desktop-process-channels": { + "id": "desktop-process-channels", + "path": "apps/desktop/src/backend/DesktopBackendManager.ts", + "start": 451, + "end": 526, + "language": "typescript", + "label": "Bootstrap, telemetry, diagnostics-control, and WSL stdin process channels", + "code": " const onOutput = options.onOutput ?? (() => Effect.void);\n const bootstrapStream = Stream.encodeText(Stream.make(`${bootstrapJson}\\n`));\n const additionalFds: Record<`fd${number}`, ChildProcess.AdditionalFdConfig> = {};\n if (options.bootstrapDelivery === \"fd3\") {\n additionalFds.fd3 = {\n type: \"input\",\n stream: bootstrapStream,\n };\n if (options.bootstrap.desktopTelemetryFd !== undefined) {\n additionalFds[`fd${options.bootstrap.desktopTelemetryFd}`] = {\n type: \"input\",\n stream: options.desktopTelemetryStream,\n };\n }\n if (options.bootstrap.desktopTelemetryControlFd !== undefined) {\n additionalFds[`fd${options.bootstrap.desktopTelemetryControlFd}`] = {\n type: \"output\",\n };\n }\n }\n const command = ChildProcess.make(options.executablePath, options.args, {\n cwd: options.cwd,\n env: options.env,\n extendEnv: options.extendEnv,\n // In Electron main, process.execPath points to the Electron binary.\n // Run the child in Node mode so this backend process does not become a GUI app instance.\n stdin: options.bootstrapDelivery === \"stdin\" ? bootstrapStream : \"ignore\",\n stdout: options.captureOutput ? \"pipe\" : \"inherit\",\n stderr: options.captureOutput ? \"pipe\" : \"inherit\",\n killSignal: \"SIGTERM\",\n forceKillAfter: DEFAULT_BACKEND_TERMINATE_GRACE,\n // wsl.exe drops additional file descriptors when forwarding to the Linux\n // side, so the WSL spawn path delivers the bootstrap envelope via stdin\n // (`--bootstrap-fd 0`) instead.\n ...(options.bootstrapDelivery === \"fd3\" ? { additionalFds } : {}),\n });\n\n const handle = yield* spawner.spawn(command).pipe(\n Effect.mapError(\n (cause) =>\n new BackendProcessSpawnError({\n executablePath: options.executablePath,\n entryPath: options.entryPath,\n cwd: options.cwd,\n httpBaseUrl: options.httpBaseUrl,\n cause,\n }),\n ),\n );\n const outputFibers: Array> = [];\n\n yield* options.onStarted?.(handle.pid) ?? Effect.void;\n if (\n options.bootstrap.desktopTelemetryControlFd !== undefined &&\n options.onDesktopTelemetryControl !== undefined\n ) {\n const controlFd = options.bootstrap.desktopTelemetryControlFd;\n const handleControl = options.onDesktopTelemetryControl;\n yield* handle.getOutputFd(controlFd).pipe(\n Stream.decodeText(),\n Stream.splitLines,\n Stream.filter((line) => line.trim().length > 0),\n Stream.runForEach((line) =>\n decodeDesktopTelemetryControlLine(line).pipe(\n Effect.flatMap(handleControl),\n Effect.catchCause((cause) =>\n logBackendProcessWarning(\"ignored invalid desktop telemetry control message\", {\n fd: controlFd,\n cause: Cause.pretty(cause),\n }),\n ),\n ),\n ),\n Effect.catchCause((cause) =>\n logBackendProcessWarning(\"desktop telemetry control stream stopped\", {\n fd: controlFd,", + "checksum": "9a38b54eef1d5d1bb2e4a11a70cac83f681b4d8369b8d44c0548c7efd93119de" + }, + "desktop-http-readiness-loop": { + "id": "desktop-http-readiness-loop", + "path": "apps/desktop/src/backend/DesktopBackendManager.ts", + "start": 566, + "end": 591, + "language": "typescript", + "label": "Repeated HTTP readiness budgets while the local child remains alive", + "code": " // Probe readiness in a loop while the backend process is still alive\n // instead of giving up after the first budget. A slow cold boot (the\n // WSL bundle loading across /mnt/c, or a first launch right after an\n // update) can exceed the initial readiness budget while the backend is\n // about to come up moments later; a one-shot probe left the app stuck\n // on \"Connecting to WSL…\" forever even though the backend kept running\n // and became healthy. Each round gets a fresh budget, and the forked\n // loop is torn down with the run scope once the child exits.\n const probeReadiness = Effect.fn(\"desktop.backendProcess.probeReadiness\")(() =>\n waitForHttpReady({\n executablePath: options.executablePath,\n entryPath: options.entryPath,\n cwd: options.cwd,\n httpBaseUrl: options.httpBaseUrl,\n timeout: options.readinessTimeout ?? DEFAULT_BACKEND_READINESS_TIMEOUT,\n }).pipe(\n Effect.flatMap(() => options.onReady?.() ?? Effect.void),\n Effect.as(true),\n Effect.catchTags({\n BackendReadinessTimeoutError: (error) =>\n (options.onReadinessFailure?.(error) ?? Effect.void).pipe(Effect.as(false)),\n }),\n ),\n );\n\n yield* probeReadiness().pipe(Effect.repeat({ while: (ready) => !ready }), Effect.forkScoped);", + "checksum": "cb8c41817f08f82de4211db178fdc26c0f9686235c75cd46ff75bf53e8c0f476" + }, + "desktop-updater-quit-boundary": { + "id": "desktop-updater-quit-boundary", + "path": "apps/desktop/src/app/DesktopLifecycle.ts", + "start": 198, + "end": 227, + "language": "typescript", + "label": "Updater-controlled quit bypasses the ordinary before-quit hold", + "code": " let updaterQuitAllowed = false;\n yield* electronTheme.onUpdated(() => {\n void runEffect(\n desktopWindow.syncAppearance.pipe(Effect.withSpan(\"desktop.lifecycle.themeUpdated\")),\n );\n });\n yield* electronApp.onBeforeQuitForUpdate(() => {\n // Electron's updater owns the remaining quit/install/relaunch sequence.\n // Cancelling the following app \"before-quit\" event breaks that sequence,\n // most visibly on macOS where the native updater performs the relaunch.\n updaterQuitAllowed = true;\n void runEffect(\n logLifecycleInfo(\"allowing updater-controlled quit\").pipe(\n Effect.withSpan(\"desktop.lifecycle.beforeQuitForUpdate\"),\n ),\n );\n });\n yield* electronApp.on(\"before-quit\", (event: Electron.Event) => {\n handleBeforeQuit(\n event,\n runEffect,\n () => quitAllowed || updaterQuitAllowed,\n () => {\n quitAllowed = true;\n },\n );\n });\n yield* electronApp.on(\"activate\", () => {\n void runEffect(\n Effect.gen(function* () {", + "checksum": "cc836843d91d37f40a435053ead939e6c9ce439e4fd7860cf814e0497261be6f" + }, + "desktop-all-instance-shutdown": { + "id": "desktop-all-instance-shutdown", + "path": "apps/desktop/src/app/DesktopApp.ts", + "start": 295, + "end": 315, + "language": "typescript", + "label": "Application finalizer gracefully stops every registered local backend", + "code": " const runId = yield* makeDesktopRunId;\n yield* Effect.annotateLogsScoped({ scope: \"desktop\", runId });\n yield* Effect.annotateCurrentSpan({ scope: \"desktop\", runId });\n\n const shutdown = yield* DesktopShutdown.DesktopShutdown;\n\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n const pool = yield* DesktopBackendPool.DesktopBackendPool;\n // Stop every backend in the pool, not just the primary. The\n // electronApp.quit() path can race ahead of the layer-scope\n // cascade, so leaving the WSL instance for its parent scope\n // finalizer means it gets hard-killed by the OS instead of\n // receiving SIGTERM + grace. Stops run concurrently.\n const instances = yield* pool.list;\n yield* Effect.forEach(instances, (instance) => instance.stop(), {\n concurrency: \"unbounded\",\n });\n }).pipe(Effect.ensuring(shutdown.markComplete)),\n );\n", + "checksum": "cd58d3b5122f8a81ad2f1f2f27e43a2e7c188f6e8a354df6ce67585070d496a9" + }, + "distribution-cli-contract": { + "id": "distribution-cli-contract", + "path": "apps/server/package.json", + "start": 1, + "end": 22, + "language": "json", + "label": "The t3 npm executable and published dist payload", + "code": "{\n \"name\": \"t3\",\n \"version\": \"0.0.33\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/pingdotgg/t3code\",\n \"directory\": \"apps/server\"\n },\n \"bin\": {\n \"t3\": \"./dist/bin.mjs\"\n },\n \"files\": [\n \"dist\"\n ],\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"node --watch src/bin.ts\",\n \"build:bundle\": \"vp pack && vp pack src/service-launcher.ts --out-dir dist --no-clean\",\n \"start\": \"node dist/bin.mjs\",\n \"typecheck\": \"tsgo --noEmit\",\n \"test\": \"vp test run\"", + "checksum": "d17e2567fc16fd9ca3b5640c87befcc259679127fb33e96434ef58249f1288f3" + }, + "distribution-cli-bundles-web": { + "id": "distribution-cli-bundles-web", + "path": "apps/server/scripts/cli.ts", + "start": 143, + "end": 176, + "language": "typescript", + "label": "CLI build copies the web renderer into the server package", + "code": "const buildCmd = Command.make(\n \"build\",\n {\n verbose: Flag.boolean(\"verbose\").pipe(Flag.withDefault(false)),\n },\n (config) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const fs = yield* FileSystem.FileSystem;\n const repoRoot = yield* RepoRoot;\n const serverDir = path.join(repoRoot, \"apps/server\");\n\n yield* Effect.log(\"[cli] Running tsdown...\");\n yield* runCommand(\n ChildProcess.make(process.execPath, [\"--run\", \"build:bundle\"], {\n cwd: serverDir,\n stdout: config.verbose ? \"inherit\" : \"ignore\",\n stderr: \"inherit\",\n shell: false,\n }),\n );\n\n const webDist = path.join(repoRoot, \"apps/web/dist\");\n const clientTarget = path.join(serverDir, \"dist/client\");\n\n if (yield* fs.exists(webDist)) {\n yield* fs.copy(webDist, clientTarget);\n yield* applyDevelopmentIconOverrides(repoRoot, serverDir);\n yield* Effect.log(\"[cli] Bundled web app into dist/client\");\n } else {\n yield* Effect.logWarning(\"[cli] Web dist not found — skipping client bundle.\");\n }\n }),\n).pipe(Command.withDescription(\"Build the server package (tsdown + bundle web client).\"));", + "checksum": "4ad46f56921042886a21ff4b2de66dd2eacebe0eb7e55c6c38cd083469e4ef47" + }, + "distribution-desktop-artifact-contract": { + "id": "distribution-desktop-artifact-contract", + "path": "scripts/build-desktop-artifact.ts", + "start": 2059, + "end": 2107, + "language": "typescript", + "label": "Desktop artifact naming, packed resources, update feed, and macOS target", + "code": " const buildConfig: Record = {\n appId: DESKTOP_APP_ID,\n productName: resolveDesktopProductName(version),\n artifactName: \"T3-Code-${version}-${arch}.${ext}\",\n electronLanguages: [...DESKTOP_ELECTRON_LANGUAGES],\n files: [...DESKTOP_FILE_EXCLUSIONS],\n directories: {\n buildResources: \"apps/desktop/resources\",\n },\n // All platforms keep app.asar fully packed; electron-builder's default\n // smart unpack extracts native libraries, which loaders find in\n // app.asar.unpacked. Windows additionally ships the server tree as the\n // hand-packed server.asar sidecar (see WINDOWS_SERVER_ASAR_RESOURCE).\n extraResources: [\n ...DESKTOP_EXTRA_RESOURCES,\n ...(platform === \"win\" ? WINDOWS_SERVER_EXTRA_RESOURCES : []),\n ],\n };\n const updateChannel = resolveDesktopUpdateChannel(version);\n const publishConfig = yield* resolveGitHubPublishConfig(updateChannel);\n if (publishConfig) {\n buildConfig.publish = [publishConfig];\n } else if (mockUpdates) {\n buildConfig.publish = [\n {\n provider: \"generic\",\n url: resolveMockUpdateServerUrl(mockUpdateServerPort),\n },\n ];\n }\n\n if (platform === \"mac\") {\n buildConfig.mac = {\n target: target === \"dmg\" ? [target, \"zip\"] : [target],\n icon: \"icon.icns\",\n category: \"public.app-category.developer-tools\",\n protocols: [\n {\n name: \"T3 Code\",\n schemes: [\"t3code\", \"t3code-dev\"],\n },\n ],\n ...(macPasskeySigning\n ? {\n entitlements: macPasskeySigning.entitlementsPath,\n provisioningProfile: macPasskeySigning.provisioningProfilePath,\n }\n : {}),\n };", + "checksum": "d86868659c92e31e0c84c37ffc43eb5d126a3dfdaa6d14e97fa9cc076312ff89" + }, + "distribution-desktop-linux-windows-targets": { + "id": "distribution-desktop-linux-windows-targets", + "path": "scripts/build-desktop-artifact.ts", + "start": 2133, + "end": 2174, + "language": "typescript", + "label": "Linux and Windows desktop target configuration", + "code": " if (platform === \"linux\") {\n buildConfig.linux = {\n target: [target],\n executableName: \"t3code\",\n icon: \"icons\",\n category: \"Development\",\n // electron-builder turns these into MimeType=x-scheme-handler/;\n // in the .desktop entry (Exec already gets %U), so browsers can hand\n // t3code:// OAuth callbacks to the app.\n protocols: [\n {\n name: \"T3 Code\",\n schemes: [\"t3code\", \"t3code-dev\"],\n },\n ],\n desktop: {\n entry: {\n StartupWMClass: \"t3code\",\n },\n },\n };\n }\n\n if (platform === \"win\") {\n buildConfig.npmRebuild = false;\n // Keep blockmap-based differential downloads enabled while changing the\n // installed file topology. The optimization is in the payload shape, not\n // in trading update bandwidth for install speed.\n buildConfig.nsis = { differentialPackage: true };\n const winConfig: Record = {\n target: [target],\n icon: \"icon.ico\",\n // Resource editing applies the product metadata and icon independently\n // of code signing. Disabling it for local unsigned builds leaves the\n // packaged executable with Electron's stock icon.\n signAndEditExecutable: true,\n };\n if (signed) {\n winConfig.azureSignOptions = yield* AzureTrustedSigningOptionsConfig;\n }\n buildConfig.win = winConfig;\n }", + "checksum": "86c6ea4e376e5cce7355d8e2c5e0471d8cfbb17be0975ca8ad5233c0ad82f39d" + }, + "distribution-release-matrix": { + "id": "distribution-release-matrix", + "path": ".github/workflows/release.yml", + "start": 342, + "end": 397, + "language": "yaml", + "label": "The four desktop artifacts actually shipped by release CI", + "code": " build:\n name: Build ${{ matrix.label }}\n # build_wsl_node_pty stays in `needs` so it runs first and its artifact is\n # available to download, but only the Windows matrix entry consumes it. We\n # therefore gate the job on preflight + relay (must succeed) WITHOUT requiring\n # build_wsl_node_pty, so a failed Linux prebuild doesn't skip the macOS/Linux\n # builds. `!cancelled()` (not `!failure()`) lets the job run even when\n # build_wsl_node_pty failed; the Windows-only download step below then fails\n # that single platform if the prebuild is missing.\n needs: [preflight, relay_public_config, build_wsl_node_pty]\n if: ${{ !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' }}\n runs-on: ${{ matrix.runner }}\n timeout-minutes: 30\n env:\n T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.relay_public_config.outputs.clerk_publishable_key }}\n T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.relay_public_config.outputs.clerk_jwt_template }}\n T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.relay_public_config.outputs.clerk_cli_oauth_client_id }}\n T3CODE_RELAY_URL: ${{ needs.relay_public_config.outputs.relay_url }}\n strategy:\n fail-fast: false\n matrix:\n include:\n - label: macOS arm64\n runner: blacksmith-12vcpu-macos-26\n platform: mac\n target: dmg\n arch: arm64\n rust_target: aarch64-apple-darwin\n resource_key: darwin-arm64\n - label: macOS x64\n runner: blacksmith-12vcpu-macos-26\n platform: mac\n target: dmg\n arch: x64\n rust_target: x86_64-apple-darwin\n resource_key: darwin-x64\n - label: Linux x64\n runner: blacksmith-32vcpu-ubuntu-2404\n platform: linux\n target: AppImage\n arch: x64\n rust_target: x86_64-unknown-linux-gnu\n resource_key: linux-x64\n - label: Windows x64\n runner: blacksmith-32vcpu-windows-2025\n platform: win\n target: nsis\n arch: x64\n rust_target: x86_64-pc-windows-msvc\n resource_key: win32-x64\n # - label: Windows arm64\n # runner: windows-11-arm\n # platform: win\n # target: nsis\n # arch: arm64\n steps:", + "checksum": "e7a92ff379e65dc8c67d6b2cbe3d5f834a4ff4a6a48fca09f395ac33d93a6dde" + }, + "distribution-cli-before-release": { + "id": "distribution-cli-before-release", + "path": ".github/workflows/release.yml", + "start": 709, + "end": 791, + "language": "yaml", + "label": "Exact CLI publication gates GitHub Release publication", + "code": " publish_cli:\n name: Publish CLI to npm\n needs: [preflight, relay_public_config, quality, build]\n if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success' }}\n runs-on: ubuntu-24.04 # blacksmith-8vcpu-ubuntu-2404\n timeout-minutes: 10\n permissions:\n contents: read\n id-token: write\n env:\n T3CODE_CLERK_PUBLISHABLE_KEY: ${{ needs.relay_public_config.outputs.clerk_publishable_key }}\n T3CODE_CLERK_JWT_TEMPLATE: ${{ needs.relay_public_config.outputs.clerk_jwt_template }}\n T3CODE_CLERK_CLI_OAUTH_CLIENT_ID: ${{ needs.relay_public_config.outputs.clerk_cli_oauth_client_id }}\n T3CODE_RELAY_URL: ${{ needs.relay_public_config.outputs.relay_url }}\n steps:\n - name: Checkout\n uses: actions/checkout@v6\n with:\n ref: ${{ needs.preflight.outputs.ref }}\n sparse-checkout: |\n /*\n !/.repos/\n sparse-checkout-cone-mode: false\n\n - name: Setup Vite+\n uses: voidzero-dev/setup-vp@v1\n with:\n node-version-file: package.json\n cache: true\n run-install: |\n args:\n - --filter=t3...\n - --filter=@t3tools/web...\n - --filter=@t3tools/scripts...\n\n - name: Download relay client tracing config\n uses: actions/download-artifact@v8\n with:\n name: relay-client-tracing-config\n path: ${{ runner.temp }}/relay-client-tracing\n\n - name: Load relay client tracing config\n shell: bash\n run: |\n config_path=\"$RUNNER_TEMP/relay-client-tracing/relay-client-tracing.env\"\n tracing_token=\"$(sed -n 's/^T3CODE_RELAY_CLIENT_OTLP_TRACES_TOKEN=//p' \"$config_path\")\"\n echo \"::add-mask::$tracing_token\"\n cat \"$config_path\" >> \"$GITHUB_ENV\"\n\n - name: Align package versions to release version\n run: node scripts/update-release-package-versions.ts \"${{ needs.preflight.outputs.version }}\"\n\n - name: Build web package\n run: vp run --filter @t3tools/web build\n\n - name: Build CLI package\n run: vp run --filter t3 build\n\n - name: Download resource monitors\n uses: actions/download-artifact@v8\n with:\n pattern: resource-monitor-*\n path: ${{ runner.temp }}/resource-monitors\n\n - name: Bundle resource monitors into CLI package\n shell: bash\n run: |\n set -euo pipefail\n for artifact_dir in \"$RUNNER_TEMP\"/resource-monitors/resource-monitor-*; do\n resource_key=\"${artifact_dir##*/resource-monitor-}\"\n target_dir=\"apps/server/dist/resource-monitor/${resource_key}\"\n mkdir -p \"$target_dir\"\n cp \"$artifact_dir\"/t3-resource-monitor* \"$target_dir/\"\n chmod +x \"$target_dir\"/t3-resource-monitor 2>/dev/null || true\n done\n\n - name: Publish CLI package\n run: node apps/server/scripts/cli.ts publish --tag \"${{ needs.preflight.outputs.cli_dist_tag }}\" --app-version \"${{ needs.preflight.outputs.version }}\" --verbose\n\n release:\n name: Publish GitHub Release\n needs: [preflight, build, publish_cli]\n if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.build.result == 'success' && needs.publish_cli.result == 'success' }}", + "checksum": "08174e0cfbd9d1a218a3690cdd7f77f0de1d49b01cf5289c2ef9097b5c164af6" + }, + "distribution-mobile-fingerprint-publish": { + "id": "distribution-mobile-fingerprint-publish", + "path": ".github/workflows/mobile-eas-production.yml", + "start": 263, + "end": 286, + "language": "yaml", + "label": "Production OTA publication requires a matching native fingerprint", + "code": " - name: Publish fingerprint-gated OTA\n if: steps.expo-token.outputs.present == 'true' && github.event_name == 'push'\n working-directory: apps/mobile\n env:\n EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}\n run: |\n message=\"$(git log -1 --pretty=%s | head -c 120) ($(git rev-parse --short=9 HEAD))\"\n for platform in ios android; do\n # eas-cli prints an environment-loaded notice to stdout before the\n # JSON even with --json, so discard everything before the document.\n hash=\"$(eas fingerprint:generate --platform \"$platform\" --environment production --json --non-interactive | sed -n '/^{/,$p' | jq -er '.hash | select(type == \"string\" and length > 0)')\"\n matching=\"$(eas build:list --platform \"$platform\" --build-profile production --status finished --fingerprint-hash \"$hash\" --limit 1 --json --non-interactive | jq 'length')\"\n if [ \"$matching\" -gt 0 ]; then\n eas update \\\n --channel production \\\n --environment production \\\n --platform \"$platform\" \\\n --message \"$message\" \\\n --non-interactive\n echo \":white_check_mark: $platform: OTA published to production (fingerprint \\`$hash\\`)\" >> \"$GITHUB_STEP_SUMMARY\"\n else\n echo \":warning: $platform: no finished production build matches fingerprint \\`$hash\\` — OTA skipped; JS changes reach $platform only once a matching build ships\" >> \"$GITHUB_STEP_SUMMARY\"\n fi\n done", + "checksum": "fe28375e5fe7f07cc02a0734c5be7cbf132acec9b52a32a9ae2b98139c8e4f31" + }, + "distribution-download-resolution": { + "id": "distribution-download-resolution", + "path": "apps/marketing/src/pages/download.astro", + "start": 89, + "end": 132, + "language": "typescript", + "label": "Marketing download links resolve against latest GitHub Release assets", + "code": "", + "checksum": "2797f24449eb4c2753ee4fc82674f127d1cd273af1aa0b25d2f7cc769b4367d0" + }, + "distribution-aur-selection": { + "id": "distribution-aur-selection", + "path": "packaging/aur/scripts/release.sh", + "start": 9, + "end": 44, + "language": "bash", + "label": "Stable and nightly tags select separate checksum-pinned AUR packages", + "code": "if [[ \"$tag\" =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\n pkgname='t3code-bin'\nelif [[ \"$tag\" =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+-nightly\\.[0-9]{8}\\.[0-9]+$ ]]; then\n pkgname='t3code-nightly-bin'\nelse\n echo \"Release $tag does not publish an AUR package.\"\n exit 0\nfi\n\nversion=\"${tag#v}\"\npkgver=\"${version//-/_}\"\nasset_name=\"T3-Code-${version}-x86_64.AppImage\"\nrelease_json=\"$(gh api \"repos/$repo/releases/tags/$tag\")\"\nasset_digest=\"$(jq -r --arg name \"$asset_name\" \\\n '.assets[] | select(.name == $name) | .digest' <<<\"$release_json\")\"\nappimage_sha256=\"${asset_digest#sha256:}\"\n\nif [[ ! \"$appimage_sha256\" =~ ^[0-9a-f]{64}$ ]]; then\n echo \"Release $tag is missing $asset_name or its SHA-256 digest.\" >&2\n exit 1\nfi\n\nwork_dir=\"$(mktemp -d)\"\ntrap 'rm -rf -- \"$work_dir\"' EXIT\ngh api -H 'Accept: application/vnd.github.raw' \\\n \"repos/$repo/contents/LICENSE?ref=$tag\" > \"$work_dir/LICENSE\"\nlicense_sha256=\"$(sha256sum \"$work_dir/LICENSE\" | awk '{print $1}')\"\n\npackage_dir=\"$repo_root/packaging/aur/$pkgname\"\ncd \"$package_dir\"\nsed -Ei \\\n -e \"s/^pkgver=.*/pkgver=$pkgver/\" \\\n -e \"s/^pkgrel=.*/pkgrel=$pkgrel/\" \\\n -e \"/# AppImage$/s/'[0-9a-f]{64}'/'$appimage_sha256'/\" \\\n -e \"/# upstream license$/s/'[0-9a-f]{64}'/'$license_sha256'/\" \\\n PKGBUILD", + "checksum": "fc2a09bb70266affc8b9779eb18da4d303cefb2ffad79934ddd803286cda7299" + }, + "release-channel-resolution": { + "id": "release-channel-resolution", + "path": ".github/workflows/release.yml", + "start": 103, + "end": 155, + "language": "bash", + "label": "Stable and nightly releases derive different versions, tags, and latest policy", + "code": " - id: release_meta\n name: Resolve release version\n shell: bash\n env:\n DISPATCH_CHANNEL: ${{ github.event.inputs.channel }}\n DISPATCH_VERSION: ${{ github.event.inputs.version }}\n NIGHTLY_DATE: ${{ github.run_started_at }}\n NIGHTLY_SHA: ${{ github.sha }}\n NIGHTLY_RUN_NUMBER: ${{ github.run_number }}\n run: |\n if [[ \"${GITHUB_EVENT_NAME}\" == \"schedule\" || ( \"${GITHUB_EVENT_NAME}\" == \"workflow_dispatch\" && \"${DISPATCH_CHANNEL:-stable}\" == \"nightly\" ) ]]; then\n nightly_date=\"$(date -u -d \"$NIGHTLY_DATE\" +%Y%m%d)\"\n\n node scripts/resolve-nightly-release.ts \\\n --date \"$nightly_date\" \\\n --run-number \"$NIGHTLY_RUN_NUMBER\" \\\n --sha \"$NIGHTLY_SHA\" \\\n --github-output\n\n echo \"release_channel=nightly\" >> \"$GITHUB_OUTPUT\"\n echo \"cli_dist_tag=nightly\" >> \"$GITHUB_OUTPUT\"\n echo \"is_prerelease=true\" >> \"$GITHUB_OUTPUT\"\n echo \"make_latest=false\" >> \"$GITHUB_OUTPUT\"\n else\n if [[ \"${GITHUB_EVENT_NAME}\" == \"workflow_dispatch\" ]]; then\n raw=\"${DISPATCH_VERSION}\"\n if [[ -z \"$raw\" ]]; then\n echo \"workflow_dispatch stable releases require the version input.\" >&2\n exit 1\n fi\n else\n raw=\"${GITHUB_REF_NAME}\"\n fi\n\n version=\"${raw#v}\"\n if [[ ! \"$version\" =~ ^[0-9]+\\.[0-9]+\\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then\n echo \"Invalid release version: $raw\" >&2\n exit 1\n fi\n\n echo \"release_channel=stable\" >> \"$GITHUB_OUTPUT\"\n echo \"version=$version\" >> \"$GITHUB_OUTPUT\"\n echo \"tag=v$version\" >> \"$GITHUB_OUTPUT\"\n echo \"name=T3 Code v$version\" >> \"$GITHUB_OUTPUT\"\n echo \"cli_dist_tag=latest\" >> \"$GITHUB_OUTPUT\"\n if [[ \"$version\" =~ ^[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\n echo \"is_prerelease=false\" >> \"$GITHUB_OUTPUT\"\n echo \"make_latest=true\" >> \"$GITHUB_OUTPUT\"\n else\n echo \"is_prerelease=true\" >> \"$GITHUB_OUTPUT\"\n echo \"make_latest=false\" >> \"$GITHUB_OUTPUT\"\n fi\n fi", + "checksum": "14a9355c1c509245042afe02fcfb4fd155578c5b31615b9440e1ca4a7375c4e7" + }, + "release-exact-version-invariant": { + "id": "release-exact-version-invariant", + "path": "docs/operations/release.md", + "start": 174, + "end": 187, + "language": "markdown", + "label": "npm exact-version publication precedes every released client", + "code": "## Server self-update release invariant\n\nConnected servers update to the client's exact version, not to an npm dist-tag. Every released\ndesktop or hosted client version must therefore have a matching `t3@` package available on\nnpm before users can receive that client.\n\nThe workflow enforces this ordering:\n\n1. `publish_cli` publishes the exact stable or nightly version to npm.\n2. `release` depends on `publish_cli` before exposing desktop artifacts in GitHub Releases.\n3. `deploy_web` depends on `release` before moving the hosted channel to the new client.\n\nPreserve these dependencies when changing the release graph. Publishing a client first would leave\nthe **Update server** action targeting a package version that does not exist yet.", + "checksum": "22eb4423a30d49b23f50117b70459bc87aacfafc9f766b8fe75d0083df4377f8" + }, + "desktop-update-check-download": { + "id": "desktop-update-check-download", + "path": "apps/desktop/src/updates/DesktopUpdates.ts", + "start": 334, + "end": 458, + "language": "typescript", + "label": "Desktop channel selection, update checks, and user-triggered download", + "code": " const applyAutoUpdaterChannel = Effect.fn(\"desktop.updates.applyAutoUpdaterChannel\")(function* (\n channel: DesktopUpdateChannel,\n ) {\n yield* Effect.annotateCurrentSpan({ channel });\n const allowsPrerelease = channel === \"nightly\";\n yield* electronUpdater.setChannel(channel);\n yield* electronUpdater.setAllowPrerelease(allowsPrerelease);\n yield* electronUpdater.setAllowDowngrade(allowsPrerelease);\n yield* electronUpdater.setFullChangelog(allowsPrerelease);\n yield* logUpdaterInfo(\"using update channel\", {\n channel,\n allowPrerelease: allowsPrerelease,\n allowDowngrade: allowsPrerelease,\n fullChangelog: allowsPrerelease,\n });\n });\n\n const shouldEnableAutoUpdates = resolveDisabledReason.pipe(Effect.map(Option.isNone));\n\n const checkForUpdates = Effect.fn(\"desktop.updates.checkForUpdates\")(function* (\n reason: string,\n actionReservation: \"acquire\" | \"held\" = \"acquire\",\n ) {\n yield* Effect.annotateCurrentSpan({ reason });\n if (yield* Ref.get(desktopState.quitting)) return false;\n if (!(yield* Ref.get(updaterConfiguredRef))) return false;\n\n const state = yield* Ref.get(updateStateRef);\n if (state.status === \"downloading\") {\n yield* logUpdaterInfo(\"skipping update check while update is active\", {\n reason,\n status: state.status,\n });\n return false;\n }\n\n if (actionReservation === \"acquire\" && !(yield* tryStartUpdateAction(\"check\"))) return false;\n\n const check = Effect.gen(function* () {\n const checkedAt = yield* currentIsoTimestamp;\n yield* setState(reduceDesktopUpdateStateOnCheckStart(state, checkedAt));\n yield* logUpdaterInfo(\"checking for updates\", { reason });\n\n return yield* electronUpdater.checkForUpdates.pipe(\n Effect.as(true),\n Effect.catchTags({\n ElectronUpdaterCheckForUpdatesError: Effect.fn(\n \"desktop.updates.handleCheckForUpdatesFailure\",\n )(function* (error) {\n const failedAt = yield* currentIsoTimestamp;\n yield* updateState((current) =>\n reduceDesktopUpdateStateOnCheckFailure(current, error.message, failedAt),\n );\n yield* logUpdaterError(error.message, {\n errorTag: error._tag,\n channel: error.channel,\n });\n return true;\n }),\n }),\n );\n });\n\n return yield* actionReservation === \"held\"\n ? check\n : check.pipe(Effect.ensuring(finishUpdateAction(\"check\")));\n });\n\n const downloadAvailableUpdate = Effect.gen(function* () {\n const state = yield* Ref.get(updateStateRef);\n if (!(yield* Ref.get(updaterConfiguredRef)) || state.status !== \"available\") {\n return { accepted: false, completed: false };\n }\n\n if (!(yield* tryStartUpdateAction(\"download\"))) {\n return { accepted: false, completed: false };\n }\n\n return yield* Effect.gen(function* () {\n yield* setState(reduceDesktopUpdateStateOnDownloadStart(state));\n yield* electronUpdater.setDisableDifferentialDownload(\n isArm64HostRunningIntelBuild(environment.runtimeInfo),\n );\n yield* logUpdaterInfo(\"downloading update\");\n yield* electronUpdater.downloadUpdate;\n return { accepted: true, completed: true };\n }).pipe(\n Effect.catchTags({\n ElectronUpdaterDownloadUpdateError: Effect.fn(\"desktop.updates.handleDownloadFailure\")(\n function* (error) {\n yield* updateState((current) =>\n reduceDesktopUpdateStateOnDownloadFailure(current, error.message),\n );\n yield* logUpdaterError(error.message, {\n errorTag: error._tag,\n channel: error.channel,\n });\n return { accepted: true, completed: false };\n },\n ),\n }),\n Effect.onInterrupt(() =>\n updateState((current) => (current.status === \"downloading\" ? state : current)).pipe(\n Effect.asVoid,\n ),\n ),\n Effect.catchCause((cause) => {\n if (Cause.hasInterruptsOnly(cause)) {\n return Effect.failCause(cause);\n }\n const error = new DesktopUpdateUnexpectedActionError({ action: \"download\", cause });\n return Effect.gen(function* () {\n yield* updateState((current) =>\n reduceDesktopUpdateStateOnDownloadFailure(current, error.message),\n );\n yield* logUpdaterError(error.message, {\n errorTag: error._tag,\n action: error.action,\n });\n return { accepted: true, completed: false };\n });\n }),\n Effect.ensuring(finishUpdateAction(\"download\")),\n );\n }).pipe(Effect.withSpan(\"desktop.updates.downloadAvailableUpdate\"));", + "checksum": "446f64f027ab1d89316bef75ed8f588b90ca57499d539bc7843dbab3994a2393" + }, + "desktop-update-install-boundary": { + "id": "desktop-update-install-boundary", + "path": "apps/desktop/src/updates/DesktopUpdates.ts", + "start": 465, + "end": 575, + "language": "typescript", + "label": "Desktop install stops every backend before updater-controlled restart", + "code": " const installDownloadedUpdate = Effect.gen(function* () {\n const state = yield* Ref.get(updateStateRef);\n const hasInstallableDownload =\n state.downloadedVersion !== null &&\n (state.status === \"downloaded\" ||\n (state.status === \"error\" &&\n (state.errorContext === null || state.errorContext === \"install\")));\n if (\n (yield* Ref.get(desktopState.quitting)) ||\n !(yield* Ref.get(updaterConfiguredRef)) ||\n !hasInstallableDownload\n ) {\n return { accepted: false, completed: false };\n }\n\n if (!(yield* tryStartUpdateAction(\"install\"))) {\n return { accepted: false, completed: false };\n }\n\n yield* Ref.set(desktopState.quitting, true);\n\n return yield* Effect.gen(function* () {\n // Stop every backend in the pool, not just the primary. With\n // parallel WSL + Windows backends, leaving the WSL instance up\n // means quitAndInstall's app.quit() exits before the pool's\n // scope cascade has a chance to run its stop finalizer, so the\n // WSL child gets hard-killed by the OS instead of receiving\n // SIGTERM + grace. Stops run concurrently with the same 5s\n // budget the primary had on its own.\n const instances = yield* pool.list;\n yield* Effect.forEach(\n instances,\n (instance) => instance.stop({ timeout: Duration.seconds(5) }),\n { concurrency: \"unbounded\" },\n );\n yield* electronWindow.destroyAll;\n yield* electronUpdater.quitAndInstall({\n isSilent: true,\n isForceRunAfter: true,\n });\n return { accepted: true, completed: false };\n }).pipe(\n Effect.catchTags({\n ElectronUpdaterQuitAndInstallError: Effect.fn(\"desktop.updates.handleInstallFailure\")(\n function* (error) {\n yield* resetInstallAction;\n yield* updateState((current) =>\n reduceDesktopUpdateStateOnInstallFailure(current, error.message),\n );\n yield* logUpdaterError(error.message, {\n errorTag: error._tag,\n channel: error.channel,\n isSilent: error.isSilent,\n isForceRunAfter: error.isForceRunAfter,\n });\n return { accepted: true, completed: false };\n },\n ),\n }),\n Effect.onInterrupt(() => resetInstallAction),\n Effect.catchCause((cause) =>\n Effect.gen(function* () {\n if (Cause.hasInterruptsOnly(cause)) {\n return yield* Effect.failCause(cause);\n }\n yield* resetInstallAction;\n const error = new DesktopUpdateUnexpectedActionError({ action: \"install\", cause });\n yield* updateState((current) =>\n reduceDesktopUpdateStateOnInstallFailure(current, error.message),\n );\n yield* logUpdaterError(error.message, {\n errorTag: error._tag,\n action: error.action,\n });\n return { accepted: true, completed: false };\n }),\n ),\n );\n }).pipe(Effect.withSpan(\"desktop.updates.installDownloadedUpdate\"));\n\n const startUpdatePollers: Effect.Effect = Effect.gen(function* () {\n yield* Effect.sleep(AUTO_UPDATE_STARTUP_DELAY).pipe(\n Effect.andThen(checkForUpdates(\"startup\")),\n Effect.catchCause((cause) => {\n if (Cause.hasInterruptsOnly(cause)) {\n return Effect.void;\n }\n const error = new DesktopUpdatePollerError({ poller: \"startup\", cause });\n return logUpdaterError(error.message, {\n errorTag: error._tag,\n poller: error.poller,\n });\n }),\n Effect.forkScoped,\n );\n yield* Effect.sleep(AUTO_UPDATE_POLL_INTERVAL).pipe(\n Effect.andThen(checkForUpdates(\"poll\")),\n Effect.forever,\n Effect.catchCause((cause) => {\n if (Cause.hasInterruptsOnly(cause)) {\n return Effect.void;\n }\n const error = new DesktopUpdatePollerError({ poller: \"poll\", cause });\n return logUpdaterError(error.message, {\n errorTag: error._tag,\n poller: error.poller,\n });\n }),\n Effect.forkScoped,\n );\n }).pipe(Effect.withSpan(\"desktop.updates.startPollers\"));", + "checksum": "c192a6561381eb1d602b20151a6d027ae2bbbf6a34ec901d4b37a3f1421d8e95" + }, + "server-update-exact-preflight": { + "id": "server-update-exact-preflight", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 64, + "end": 169, + "language": "typescript", + "label": "Server self-update accepts only an exact version that passes staged preflight", + "code": " const update: ServerSelfUpdate[\"Service\"][\"update\"] = Effect.fn(\n \"cloud.server_self_update.update\",\n )(function* (input, reportProgress = () => Effect.void) {\n if (capability === \"desktop-managed\") {\n return yield* failWith(\n \"This server is managed by the T3 Code desktop app on its machine; update the desktop app to update it.\",\n );\n }\n if (capability === null) {\n return yield* failWith(\n \"Remote updates require the T3 Code background service. Run `t3 service install` on the server machine.\",\n );\n }\n\n const targetVersion = input.targetVersion.trim();\n if (!isExactServiceVersion(targetVersion)) {\n return yield* failWith(`'${targetVersion}' is not an exact t3 version.`);\n }\n if (yield* Ref.getAndSet(inFlight, true)) {\n return yield* failWith(\"A server update is already in progress.\");\n }\n\n return yield* Effect.gen(function* () {\n yield* reportProgress(\"downloading\");\n const paths = yield* ensurePinnedRuntimeInstalled({\n baseDir: serverConfig.baseDir,\n version: targetVersion,\n fs,\n path,\n runner,\n validate: (runtime) =>\n runner\n .run({\n command: execPath,\n args: [\n runtime.entryPath,\n \"__service-preflight\",\n \"--database-path\",\n serverConfig.dbPath,\n \"--launcher-protocol\",\n String(SERVICE_LAUNCHER_PROTOCOL),\n ],\n timeout: PREFLIGHT_TIMEOUT,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new PinnedRuntimeInstallError({\n step: \"running the staged service preflight\",\n cause,\n }),\n ),\n Effect.flatMap(\n (\n result,\n ): Effect.Effect<\n void,\n PinnedRuntimeInstallError | PinnedRuntimePreflightBlockedError\n > => {\n if (result.code !== 0) {\n return Effect.fail(\n new PinnedRuntimeInstallError({\n step: \"running the staged service preflight\",\n exitCode: Number(result.code),\n stdoutLength: result.stdout.length,\n stderrLength: result.stderr.length,\n }),\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout.trim());\n } catch (cause) {\n return Effect.fail(\n new PinnedRuntimeInstallError({\n step: \"decoding the staged service preflight\",\n cause,\n }),\n );\n }\n const preflight = decodeServicePreflightResult(parsed);\n if (preflight === undefined || preflight.version !== targetVersion) {\n return Effect.fail(\n new PinnedRuntimeInstallError({\n step: \"verifying the staged service preflight\",\n }),\n );\n }\n return preflight.status === \"ready\"\n ? Effect.void\n : Effect.fail(\n new PinnedRuntimePreflightBlockedError({\n version: targetVersion,\n reason: preflight.reason,\n }),\n );\n },\n ),\n ),\n }).pipe(\n Effect.mapError((error) =>\n error._tag === \"PinnedRuntimePreflightBlockedError\"\n ? failWith(error.reason, error)\n : failWith(`Could not prepare t3@${targetVersion}.`, error),\n ),\n );", + "checksum": "2024b45fe781d2feca6c8eb96b8b543c146198449303cc50ed7d838efa3e3ab3" + }, + "server-update-launcher-handoff": { + "id": "server-update-launcher-handoff", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 171, + "end": 191, + "language": "typescript", + "label": "Prepared server runtime is handed to the stable launcher by update id", + "code": " yield* reportProgress(\"installing\");\n const updateId = yield* launcher\n .requestUpdate({ targetVersion, dbPath: serverConfig.dbPath })\n .pipe(\n Effect.mapError((error) =>\n failWith(\n error._tag === \"ServiceLauncherRejectedError\"\n ? error.reason\n : \"Could not ask the service launcher to activate the prepared update.\",\n error,\n ),\n ),\n );\n\n yield* Effect.logInfo(\"Server update prepared; handing off to the service launcher.\", {\n updateId,\n targetVersion,\n runtimePath: paths.entryPath,\n });\n return { targetVersion, method: \"boot-service\" as const, updateId };\n }).pipe(Effect.onError(() => Ref.set(inFlight, false)));", + "checksum": "ce552ec0f0f18d4a12f7a90044b4492a886c4e35c1044f3bedf158442e4ec62b" + }, + "mobile-ota-fingerprint-policy": { + "id": "mobile-ota-fingerprint-policy", + "path": "apps/mobile/app.config.ts", + "start": 159, + "end": 180, + "language": "typescript", + "label": "Mobile runtime compatibility is keyed by native fingerprint", + "code": "const config: ExpoConfig = {\n name: variant.appName,\n slug: \"t3-code\",\n platforms: [\"ios\", \"android\"],\n scheme: variant.scheme,\n version: \"1.0.4\",\n runtimeVersion: {\n // Fingerprint (not appVersion) so an OTA only reaches binaries whose native\n // project — native deps, config plugins, AND patches/ — matches the update.\n // With appVersion, every 0.1.0 build shares a runtime version, so a JS update\n // could land on a binary missing the native changes it needs and crash.\n policy: process.env.MOBILE_VERSION_POLICY ?? \"fingerprint\",\n },\n orientation: \"portrait\",\n icon: variant.assets.appIcon,\n userInterfaceStyle: \"automatic\",\n updates: {\n enabled: true,\n url: \"https://u.expo.dev/d763fcb8-d37c-41ea-a773-b54a0ab4a454\",\n checkAutomatically: \"ON_LOAD\",\n fallbackToCacheTimeout: 0,\n },", + "checksum": "8fca9ce8ca5fe7a6a1fa27d63f6bef643e0df47b68108ea3c1bbb3d29227b3a2" + }, + "analytics-posthog-controls": { + "id": "analytics-posthog-controls", + "path": "apps/server/src/telemetry/AnalyticsService.ts", + "start": 31, + "end": 44, + "language": "typescript", + "label": "PostHog destination, opt-out, and bounded buffer configuration", + "code": "const TelemetryEnvConfig = Config.all({\n posthogKey: Config.string(\"T3CODE_POSTHOG_KEY\").pipe(\n Config.withDefault(\"phc_XOWci4oZP4VvLiEyrFqkFjP4CZn55mjYYBMREK5Wd6m\"),\n ),\n posthogHost: Config.string(\"T3CODE_POSTHOG_HOST\").pipe(\n Config.withDefault(\"https://us.i.posthog.com\"),\n ),\n enabled: Config.boolean(\"T3CODE_TELEMETRY_ENABLED\").pipe(Config.withDefault(true)),\n flushBatchSize: Config.number(\"T3CODE_TELEMETRY_FLUSH_BATCH_SIZE\").pipe(Config.withDefault(20)),\n maxBufferedEvents: Config.number(\"T3CODE_TELEMETRY_MAX_BUFFERED_EVENTS\").pipe(\n Config.withDefault(1_000),\n ),\n wslDistroName: Config.string(\"WSL_DISTRO_NAME\").pipe(Config.option),\n});", + "checksum": "f3c3ac2e572cef41e21529c9b74a5142da3d04ae2b8f5b948096e8eb497141c9" + }, + "analytics-posthog-boundary": { + "id": "analytics-posthog-boundary", + "path": "apps/server/src/telemetry/AnalyticsService.ts", + "start": 69, + "end": 134, + "language": "typescript", + "label": "Installation-scoped analytics payload and PostHog batch boundary", + "code": "export const make = Effect.gen(function* () {\n const telemetryConfig = yield* TelemetryEnvConfig;\n const httpClient = yield* HttpClient.HttpClient;\n const serverConfig = yield* ServerConfig.ServerConfig;\n const identifier = yield* getTelemetryIdentifier;\n const bufferRef = yield* Ref.make>([]);\n const clientType = serverConfig.mode === \"desktop\" ? \"desktop-app\" : \"cli-web-client\";\n const hostPlatform = yield* HostProcessPlatform;\n const hostArchitecture = yield* HostProcessArchitecture;\n\n const enqueueBufferedEvent = (event: string, properties?: Readonly>) =>\n Effect.flatMap(DateTime.now, (now) =>\n Ref.modify(bufferRef, (current) => {\n const appended = [\n ...current,\n {\n event,\n ...(properties ? { properties } : {}),\n capturedAt: DateTime.formatIso(now),\n } satisfies BufferedAnalyticsEvent,\n ];\n\n const next =\n appended.length > telemetryConfig.maxBufferedEvents\n ? appended.slice(appended.length - telemetryConfig.maxBufferedEvents)\n : appended;\n\n return [\n {\n size: next.length,\n dropped: next.length !== appended.length,\n } as const,\n next,\n ] as const;\n }),\n );\n\n const sendBatch = Effect.fn(\"AnalyticsService.sendBatch\")(function* (\n events: ReadonlyArray,\n ) {\n if (!telemetryConfig.enabled || !identifier) return;\n\n const payload = {\n api_key: telemetryConfig.posthogKey,\n batch: events.map((event) => ({\n event: event.event,\n distinct_id: identifier,\n properties: {\n ...event.properties,\n $process_person_profile: false,\n platform: hostPlatform,\n wsl: Option.getOrUndefined(telemetryConfig.wslDistroName),\n arch: hostArchitecture,\n t3CodeVersion: packageJson.version,\n clientType,\n },\n timestamp: event.capturedAt,\n })),\n };\n\n yield* HttpClientRequest.post(`${telemetryConfig.posthogHost}/batch/`).pipe(\n HttpClientRequest.bodyJson(payload),\n Effect.flatMap(httpClient.execute),\n Effect.flatMap(HttpClientResponse.filterStatusOk),\n );\n });", + "checksum": "80a1888ab4ce1d23e1388a370d7d82c5313eeb46c325eb8d74c5609a55b8a82a" + }, + "analytics-identity-ladder": { + "id": "analytics-identity-ladder", + "path": "apps/server/src/telemetry/Identify.ts", + "start": 248, + "end": 299, + "language": "typescript", + "label": "Hashed Codex, Claude, then anonymous analytics identity ladder", + "code": "/**\n * getTelemetryIdentifier - Users are \"identified\" by finding the first match of the following, then hashing the value.\n * 1. ~/.codex/auth.json tokens.account_id\n * 2. ~/.claude.json userID\n * 3. ~/.t3/telemetry/anonymous-id\n */\nexport const getTelemetryIdentifierForHome = Effect.fn(\"getTelemetryIdentifierForHome\")(\n function* (homeDirectory: string) {\n const codexAccountId = yield* getCodexAccountId(homeDirectory).pipe(\n Effect.catchTags({\n TelemetryIdentityReadError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n TelemetryIdentityDecodeError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n }),\n );\n if (Option.isSome(codexAccountId)) {\n return yield* hash(\"codex\", codexAccountId.value);\n }\n\n const claudeUserId = yield* getClaudeUserId(homeDirectory).pipe(\n Effect.catchTags({\n TelemetryIdentityReadError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n TelemetryIdentityDecodeError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n }),\n );\n if (Option.isSome(claudeUserId)) {\n return yield* hash(\"claude\", claudeUserId.value);\n }\n\n const anonymousId = yield* upsertAnonymousId.pipe(\n Effect.map(Option.some),\n Effect.catchTags({\n TelemetryIdentityReadError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n TelemetryAnonymousIdGenerationError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n TelemetryAnonymousIdPersistenceError: (error) =>\n logTelemetryIdentityError(error).pipe(Effect.as(Option.none())),\n }),\n );\n if (Option.isSome(anonymousId)) {\n return yield* hash(\"anonymous\", anonymousId.value);\n }\n\n return null;\n },\n Effect.tapError(logTelemetryIdentityError),\n Effect.orElseSucceed(() => null),\n);", + "checksum": "faea0eb8f89de6534789b7d542ee9f8ca43255aea1750edd5948f682e9a41018" + }, + "observability-local-remote-lanes": { + "id": "observability-local-remote-lanes", + "path": "apps/server/src/observability/Layers/Observability.ts", + "start": 19, + "end": 93, + "language": "typescript", + "label": "Local trace sink remains active while OTLP traces and metrics are optional", + "code": "export const ObservabilityLive = Layer.unwrap(\n Effect.gen(function* () {\n const config = yield* ServerConfig.ServerConfig;\n const attribution = yield* ResourceAttribution.ResourceAttribution;\n\n const traceReferencesLayer = Layer.mergeAll(\n Layer.succeed(Tracer.MinimumTraceLevel, config.traceMinLevel),\n Layer.succeed(References.TracerTimingEnabled, config.traceTimingEnabled),\n httpHeaderRedactionLayer,\n );\n\n const tracerLayer = Layer.unwrap(\n Effect.gen(function* () {\n const sink = yield* makeTraceSink({\n filePath: config.serverTracePath,\n maxBytes: config.traceMaxBytes,\n maxFiles: config.traceMaxFiles,\n batchWindowMs: config.traceBatchWindowMs,\n onFlush: (stats) =>\n attribution.record({\n component: \"server-trace\",\n operation: \"append\",\n logicalWriteBytes: stats.logicalWriteBytes,\n count: stats.count,\n durationMs: stats.durationMs,\n }),\n });\n const delegate =\n config.otlpTracesUrl === undefined\n ? undefined\n : yield* OtlpTracer.make({\n url: config.otlpTracesUrl,\n exportInterval: `${config.otlpExportIntervalMs} millis`,\n resource: {\n serviceName: config.otlpServiceName,\n attributes: {\n \"service.runtime\": \"t3-server\",\n \"service.mode\": config.mode,\n },\n },\n });\n\n const tracer = yield* makeLocalFileTracer({\n filePath: config.serverTracePath,\n maxBytes: config.traceMaxBytes,\n maxFiles: config.traceMaxFiles,\n batchWindowMs: config.traceBatchWindowMs,\n sink,\n ...(delegate ? { delegate } : {}),\n });\n\n return Layer.mergeAll(\n Layer.succeed(Tracer.Tracer, tracer),\n BrowserTraceCollector.layer(sink),\n );\n }),\n ).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));\n\n const metricsLayer =\n config.otlpMetricsUrl === undefined\n ? Layer.empty\n : OtlpMetrics.layer({\n url: config.otlpMetricsUrl,\n exportInterval: `${config.otlpExportIntervalMs} millis`,\n resource: {\n serviceName: config.otlpServiceName,\n attributes: {\n \"service.runtime\": \"t3-server\",\n \"service.mode\": config.mode,\n },\n },\n }).pipe(Layer.provideMerge(otlpSerializationLayer));\n\n return Layer.mergeAll(ServerLoggerLive, traceReferencesLayer, tracerLayer, metricsLayer);\n }),", + "checksum": "17644127b1a5444891920976b4f660fd3be2843d14f8d933394aad5b5c24f390" + }, + "observability-browser-ingest": { + "id": "observability-browser-ingest", + "path": "apps/server/src/http.ts", + "start": 146, + "end": 199, + "language": "typescript", + "label": "Authenticated browser traces land locally before optional OTLP forwarding", + "code": "export const otlpTracesProxyRouteLayer = HttpRouter.add(\n \"POST\",\n OTLP_TRACES_PROXY_PATH,\n Effect.gen(function* () {\n yield* authenticateRawRouteWithScope(AuthOrchestrationOperateScope);\n const request = yield* HttpServerRequest.HttpServerRequest;\n const config = yield* ServerConfig.ServerConfig;\n const otlpTracesUrl = config.otlpTracesUrl;\n const browserTraceCollector = yield* BrowserTraceCollector.BrowserTraceCollector;\n const httpClient = yield* HttpClient.HttpClient;\n const bodyJson = cast(yield* request.json);\n\n yield* Effect.try({\n try: () => decodeOtlpTraceRecords(bodyJson),\n catch: (cause) => new DecodeOtlpTraceRecordsError({ cause, bodyJson }),\n }).pipe(\n Effect.flatMap((records) => browserTraceCollector.record(records)),\n Effect.catch((cause) =>\n Effect.logWarning(\"Failed to decode browser OTLP traces\", {\n cause,\n bodyJson,\n }),\n ),\n );\n\n if (otlpTracesUrl === undefined) {\n return HttpServerResponse.empty({ status: 204 });\n }\n\n return yield* httpClient\n .post(otlpTracesUrl, {\n body: HttpBody.jsonUnsafe(bodyJson),\n })\n .pipe(\n Effect.flatMap(HttpClientResponse.filterStatusOk),\n Effect.as(HttpServerResponse.empty({ status: 204 })),\n Effect.tapError((cause) =>\n Effect.logWarning(\"Failed to export browser OTLP traces\", {\n cause,\n otlpTracesUrl,\n }),\n ),\n Effect.orElseSucceed(() =>\n HttpServerResponse.text(\"Trace export failed.\", { status: 502 }),\n ),\n );\n }).pipe(\n Effect.catchTags({\n EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,\n EnvironmentInternalError: HttpServerRespondable.toResponse,\n EnvironmentScopeRequiredError: HttpServerRespondable.toResponse,\n }),\n ),\n);", + "checksum": "220e35097ba87ab35826ac3da655a6551055a457378aba8aaa77c21f843990c0" + }, + "resource-telemetry-demand-history": { + "id": "resource-telemetry-demand-history", + "path": "docs/internals/resource-telemetry.md", + "start": 129, + "end": 170, + "language": "markdown", + "label": "Bounded native history and diagnostics-driven telemetry streaming", + "code": "### Native history and streaming\n\nEvery native sample is appended to a one-hour in-memory ring bounded to 3,600\nsnapshots, 20,000 retained process rows, and 64 MiB of retained history bytes.\nHistory stays in the sidecar until a `readHistory` request and is returned in\nbounded chunks. The first bound reached wins, so high process counts or large\nprocess names and command lines shorten the effective history window.\n\nPeriodic snapshot streaming is disabled by default. The server enables it only\nwhile at least one diagnostics subscription is retained. `sampleNow` remains\navailable for explicit refreshes and identity validation.\n\nThe server adjusts native sampling without restarting the sidecar:\n\n- suspended, locked, low-power, or serious/critical thermal state: 15 seconds;\n- battery: 5 seconds;\n- normal AC: 1 second;\n- unknown or stale power: 5 seconds in the background and 1 second while live\n diagnostics is open.\n\n### Sampling limits\n\nThis is counter sampling, not syscall tracing.\n\n- A process that starts and exits entirely between samples may not be observed.\n- Cumulative CPU and I/O counters still provide accurate deltas for processes\n that survive across samples.\n- Exact file paths, individual write syscalls, ETW events, eBPF events, and\n Endpoint Security events are outside this implementation.\n\nThose deeper tracing systems can be added later as opt-in diagnostic modes\nwithout changing the public `ResourceTelemetry` model.\n\n## I/O semantics\n\nThe monitor preserves platform semantics instead of presenting all counters as\nequivalent:\n\n- Unix-like platforms report storage I/O counters exposed by `sysinfo`.\n- Windows reports all process I/O bytes, not only disk bytes.\n- Operating-system caches can prevent logical application reads or writes from\n appearing as physical storage bytes.", + "checksum": "5bc90ad0498b5f6e9b3dfc618b9d6f42d05938c26dfb3dcdc8b98d01446d89f7" + }, + "connect-oauth-hosted-handoff": { + "id": "connect-oauth-hosted-handoff", + "path": "packages/shared/src/connectAuth.ts", + "start": 19, + "end": 104, + "language": "typescript", + "label": "Hosted OAuth handoff and loopback versus out-of-band callbacks", + "code": "/**\n * Requested at authorize time by the hosted page and honored by the CLI's\n * token exchange; keep both sides on this single definition.\n */\nexport const CONNECT_OAUTH_SCOPES = [\"openid\", \"profile\", \"email\"] as const;\n\nexport interface ConnectAuthorizeRequest {\n readonly state: string;\n readonly challenge: string;\n /**\n * Present when a loopback CLI initiated the request: the hosted /connect\n * page then asks Clerk to redirect the authorization code straight to\n * `http://127.0.0.1:/callback` instead of the hosted callback page.\n */\n readonly loopbackPort?: number;\n}\n\n/**\n * The URL the CLI prints for the user to open in a browser. `state` and\n * `code_challenge` ride the fragment so they never reach the hosted app's\n * server or CDN logs; neither is a secret.\n *\n * Both CLI flows route through the hosted /connect page rather than hitting\n * Clerk's /oauth/authorize directly: a signed-out browser sent straight to\n * /oauth/authorize goes through Clerk's sign-in redirect, which does not\n * reliably preserve the authorize query parameters (state, response_type,\n * code_challenge). The hosted page waits for a Clerk session first, then\n * forwards the request with the parameters intact.\n */\nexport function buildConnectAuthorizeRequestUrl(input: {\n readonly hostedAppUrl: string;\n readonly state: string;\n readonly challenge: string;\n readonly loopbackPort?: number;\n}): string {\n const url = new URL(CONNECT_AUTHORIZE_PATH, input.hostedAppUrl);\n url.hash = new URLSearchParams([\n [CONNECT_AUTH_STATE_PARAM, input.state],\n [CONNECT_AUTH_CHALLENGE_PARAM, input.challenge],\n ...(input.loopbackPort === undefined\n ? []\n : [[CONNECT_AUTH_PORT_PARAM, String(input.loopbackPort)] as [string, string]]),\n ]).toString();\n return url.toString();\n}\n\nexport function readConnectAuthorizeRequest(url: URL): ConnectAuthorizeRequest | null {\n const params = readHashParams(url);\n const state = params.get(CONNECT_AUTH_STATE_PARAM)?.trim() ?? \"\";\n const challenge = params.get(CONNECT_AUTH_CHALLENGE_PARAM)?.trim() ?? \"\";\n if (!state || !challenge) {\n return null;\n }\n const port = params.get(CONNECT_AUTH_PORT_PARAM);\n if (port === null) {\n return { state, challenge };\n }\n // A present-but-invalid port means the link was corrupted; reject the whole\n // request rather than silently downgrading a loopback flow to the\n // out-of-band one, which would strand the waiting CLI.\n const loopbackPort = parseLoopbackPort(port.trim());\n if (loopbackPort === null) {\n return null;\n }\n return { state, challenge, loopbackPort };\n}\n\nfunction parseLoopbackPort(value: string): number | null {\n if (!/^\\d{1,5}$/.test(value)) {\n return null;\n }\n const port = Number(value);\n return port >= 1 && port <= 65535 ? port : null;\n}\n\n/**\n * Redirect URI for the CLI's local callback listener. Must stay in sync with\n * the redirect URI registered on the Clerk CLI OAuth application.\n */\nexport function connectLoopbackRedirectUri(port: number): string {\n return `http://127.0.0.1:${port}${CONNECT_LOOPBACK_CALLBACK_PATH}`;\n}\n\nexport function connectCallbackUrl(hostedAppUrl: string): string {\n return new URL(CONNECT_CALLBACK_PATH, hostedAppUrl).toString();\n}", + "checksum": "019508052e9e226164594a9bd72a85bf869819e0c3de33c5d0f4865e25decbbb" + }, + "connect-oauth-cli-pkce": { + "id": "connect-oauth-cli-pkce", + "path": "apps/server/src/cloud/CliTokenManager.ts", + "start": 266, + "end": 323, + "language": "typescript", + "label": "CLI PKCE, state validation, and authorization-code exchange", + "code": "const makePkceRequest = Effect.gen(function* () {\n const crypto = yield* Crypto.Crypto;\n const verifier = Encoding.encodeBase64Url(yield* crypto.randomBytes(32));\n const challenge = Encoding.encodeBase64Url(\n yield* crypto.digest(\"SHA-256\", new TextEncoder().encode(verifier)),\n );\n const state = Encoding.encodeBase64Url(yield* crypto.randomBytes(16));\n return { verifier, challenge, state };\n});\n\nexport interface OutOfBandOAuthPromptInput {\n readonly authorizeUrl: string;\n readonly validate: (value: string) => Effect.Effect;\n}\n\n/**\n * Out-of-band OAuth for machines without a local browser (SSH). The user\n * opens the hosted /connect URL elsewhere, signs in, and enters the displayed\n * code in this terminal. The PKCE verifier never leaves this process, so the\n * authorization code is useless to an observer, and the state bundled into\n * the blob preserves the loopback flow's CSRF check.\n */\nexport const outOfBandOAuthLogin = Effect.fn(\"cloud.cli_token.out_of_band_oauth_login\")(function* <\n E,\n R,\n>(promptForCode: (input: OutOfBandOAuthPromptInput) => Effect.Effect) {\n const metadata = yield* cloudCliOAuthConfig;\n const hostedAppUrl = yield* hostedAppUrlConfig;\n const { verifier, challenge, state } = yield* makePkceRequest;\n\n const authorizationCode = yield* promptForCode({\n authorizeUrl: buildConnectAuthorizeRequestUrl({ hostedAppUrl, state, challenge }),\n validate: (value) => {\n const checked = checkConnectAuthCode(value, state);\n return typeof checked === \"string\" ? Effect.fail(checked) : Effect.succeed(value);\n },\n }).pipe(\n // Clerk authorization codes expire on this horizon anyway; matching the\n // loopback flow's timeout turns an abandoned prompt into a clear error.\n Effect.timeout(CLOUD_CLI_OAUTH_CALLBACK_TIMEOUT),\n Effect.catchTag(\"TimeoutError\", (cause) =>\n Effect.fail(new CloudCliAuthorizationTimeoutError({ cause })),\n ),\n );\n // promptForCode is caller-supplied, so re-check the returned value rather\n // than trusting that the prompt ran validate.\n const authCode = checkConnectAuthCode(authorizationCode, state);\n if (typeof authCode === \"string\") {\n return yield* new CloudCliAuthorizationError({ cause: authCode });\n }\n\n return yield* exchangeToken(metadata, {\n grant_type: \"authorization_code\",\n code: authCode.code,\n redirect_uri: connectCallbackUrl(hostedAppUrl),\n client_id: metadata.clientId,\n code_verifier: verifier,\n });", + "checksum": "0c0afa4526b464e06018e6ceb78ba3bbcfd588ced7303dbd9b515a9a5f7cedd8" + }, + "connect-browser-dpop-key": { + "id": "connect-browser-dpop-key", + "path": "apps/web/src/cloud/dpop.ts", + "start": 24, + "end": 143, + "language": "typescript", + "label": "Browser P-256 DPoP key storage, generation, and thumbprint", + "code": "const DPOP_DATABASE_NAME = \"t3code:cloud-auth\";\nconst DPOP_DATABASE_VERSION = 1;\nconst DPOP_KEY_STORE_NAME = \"keys\";\nconst DPOP_KEY_ID = \"relay-dpop-proof-key\";\nconst decodeDpopPublicJwk = Schema.decodeUnknownEffect(DpopPublicJwk);\n\nexport const browserCryptoLayer = Layer.succeed(\n Crypto.Crypto,\n Crypto.make({\n randomBytes: (size) => globalThis.crypto.getRandomValues(new Uint8Array(size)),\n digest: (algorithm, data) =>\n Effect.promise(async () => {\n const input = new Uint8Array(data.length);\n input.set(data);\n return new Uint8Array(await globalThis.crypto.subtle.digest(algorithm, input.buffer));\n }),\n }),\n);\n\nfunction dpopError(message: string, cause?: unknown) {\n return new BrowserDpopError({ message, ...(cause === undefined ? {} : { cause }) });\n}\n\nfunction openDpopDatabase(): Effect.Effect {\n return Effect.callback((resume) => {\n const request = indexedDB.open(DPOP_DATABASE_NAME, DPOP_DATABASE_VERSION);\n request.addEventListener(\"error\", () =>\n resume(\n Effect.fail(dpopError(\"Could not open DPoP key storage.\", request.error ?? undefined)),\n ),\n );\n request.addEventListener(\"upgradeneeded\", () => {\n if (!request.result.objectStoreNames.contains(DPOP_KEY_STORE_NAME)) {\n request.result.createObjectStore(DPOP_KEY_STORE_NAME);\n }\n });\n request.addEventListener(\"success\", () => resume(Effect.succeed(request.result)));\n });\n}\n\nexport function readStoredBrowserDpopKey(): Effect.Effect {\n if (typeof indexedDB === \"undefined\") {\n return Effect.succeed(null);\n }\n return Effect.acquireUseRelease(\n openDpopDatabase(),\n (database) =>\n Effect.callback((resume) => {\n const request = database\n .transaction(DPOP_KEY_STORE_NAME, \"readonly\")\n .objectStore(DPOP_KEY_STORE_NAME)\n .get(DPOP_KEY_ID);\n request.addEventListener(\"error\", () =>\n resume(Effect.fail(dpopError(\"Could not read DPoP key.\", request.error ?? undefined))),\n );\n request.addEventListener(\"success\", () =>\n resume(Effect.succeed((request.result as BrowserDpopKey | undefined) ?? null)),\n );\n }),\n (database) => Effect.sync(() => database.close()),\n );\n}\n\nexport function writeStoredBrowserDpopKey(\n key: BrowserDpopKey,\n): Effect.Effect {\n if (typeof indexedDB === \"undefined\") {\n return Effect.void;\n }\n return Effect.acquireUseRelease(\n openDpopDatabase(),\n (database) =>\n Effect.callback((resume) => {\n const transaction = database.transaction(DPOP_KEY_STORE_NAME, \"readwrite\");\n transaction.addEventListener(\"error\", () =>\n resume(\n Effect.fail(dpopError(\"Could not write DPoP key.\", transaction.error ?? undefined)),\n ),\n );\n transaction.addEventListener(\"complete\", () => resume(Effect.void));\n transaction.objectStore(DPOP_KEY_STORE_NAME).put(key, DPOP_KEY_ID);\n }),\n (database) => Effect.sync(() => database.close()),\n );\n}\n\nexport const generateBrowserDpopKey = Effect.gen(function* () {\n const generated = yield* Effect.tryPromise({\n try: () =>\n crypto.subtle.generateKey({ name: \"ECDSA\", namedCurve: \"P-256\" }, true, [\n \"sign\",\n \"verify\",\n ]) as Promise,\n catch: (cause) => dpopError(\"Could not generate DPoP proof key.\", cause),\n });\n const privateJwk = yield* Effect.tryPromise({\n try: () => crypto.subtle.exportKey(\"jwk\", generated.privateKey),\n catch: (cause) => dpopError(\"Could not export DPoP private key.\", cause),\n });\n const publicJwk = yield* Effect.tryPromise({\n try: () => crypto.subtle.exportKey(\"jwk\", generated.publicKey),\n catch: (cause) => dpopError(\"Could not export DPoP public key.\", cause),\n }).pipe(\n Effect.flatMap((jwk) => decodeDpopPublicJwk(jwk)),\n Effect.mapError((cause) =>\n cause instanceof BrowserDpopError\n ? cause\n : dpopError(\"Generated DPoP public key is invalid.\", cause),\n ),\n );\n const privateKey = yield* Effect.tryPromise({\n try: () => importJWK(privateJwk as JWK, \"ES256\", { extractable: false }) as Promise,\n catch: (cause) => dpopError(\"Could not import DPoP private key.\", cause),\n });\n return {\n privateKey,\n publicJwk,\n thumbprint: computeDpopJwkThumbprint(publicJwk),\n };\n});", + "checksum": "6a8194ca1a98d84a004e00c32168993c56318488d07f4c377c7ecfebf192d7c5" + }, + "connect-environment-link-handshake": { + "id": "connect-environment-link-handshake", + "path": "apps/web/src/cloud/linkEnvironment.ts", + "start": 402, + "end": 493, + "language": "typescript", + "label": "Client-side relay challenge, environment proof, link, and runtime setup", + "code": "export function linkPrimaryEnvironmentToCloud(input: {\n readonly target: CloudLinkTarget;\n readonly clerkToken: string;\n readonly mode?: CloudLinkMode;\n}): Effect.Effect<\n void,\n CloudEnvironmentLinkError,\n EnvironmentRegistry | HttpClient.HttpClient | ManagedRelay.ManagedRelayClient\n> {\n return Effect.gen(function* () {\n const configuredRelayUrl = relayUrl();\n if (!configuredRelayUrl) {\n return yield* new CloudEnvironmentLinkError({\n message: \"T3CODE_RELAY_URL is not configured.\",\n });\n }\n const managedTunnelsEnabled = (input.mode ?? \"managed\") === \"managed\";\n const providerKind = managedTunnelsEnabled\n ? MANAGED_ENDPOINT_PROVIDER_KIND\n : PUBLISH_ONLY_PROVIDER_KIND;\n const relayClient = yield* ManagedRelay.ManagedRelayClient;\n const environmentClient = yield* makeEnvironmentHttpApiClient(input.target.httpBaseUrl);\n if (managedTunnelsEnabled) {\n yield* ensureRelayClientAvailable(EnvironmentId.make(input.target.environmentId));\n }\n\n const challenge = yield* relayClient\n .createEnvironmentLinkChallenge({\n clerkToken: input.clerkToken,\n payload: {\n notificationsEnabled: true,\n liveActivitiesEnabled: true,\n managedTunnelsEnabled,\n },\n })\n .pipe(\n Effect.mapError(\n decodedRelayClientError(\n `${configuredRelayUrl}/v1/client/environment-link-challenges failed`,\n ),\n ),\n );\n const proof = yield* environmentClient.connect\n .linkProof({\n headers: {},\n payload: {\n challenge: challenge.challenge,\n relayIssuer: configuredRelayUrl,\n endpoint: {\n httpBaseUrl: input.target.httpBaseUrl,\n wsBaseUrl: input.target.wsBaseUrl,\n providerKind,\n },\n origin: endpointOrigin(input.target.httpBaseUrl),\n },\n })\n .pipe(Effect.mapError(environmentApiError(\"Could not obtain environment link proof.\")));\n const link = yield* relayClient\n .linkEnvironment({\n clerkToken: input.clerkToken,\n payload: {\n proof,\n notificationsEnabled: true,\n liveActivitiesEnabled: true,\n managedTunnelsEnabled,\n },\n })\n .pipe(\n Effect.mapError(\n decodedRelayClientError(`${configuredRelayUrl}/v1/client/environment-links failed`),\n ),\n );\n yield* ensureLinkedEnvironmentMatches({\n expectedEnvironmentId: input.target.environmentId,\n expectedProviderKind: providerKind,\n link,\n });\n\n yield* environmentClient.connect\n .relayConfig({\n headers: {},\n payload: {\n relayUrl: configuredRelayUrl,\n relayIssuer: link.relayIssuer,\n cloudUserId: link.cloudUserId,\n environmentCredential: link.environmentCredential,\n cloudMintPublicKey: link.cloudMintPublicKey,\n endpointRuntime: link.endpointRuntime,\n },\n })\n .pipe(Effect.mapError(environmentApiError(\"Could not configure environment relay access.\")));\n }).pipe(Effect.provide(primaryEnvironmentHttpLayer));", + "checksum": "205bb065dd80ce2f8b9cc5b0a127f436a52d7654918dbe64c11a55556a788dd1" + }, + "connect-relay-linker-provision": { + "id": "connect-relay-linker-provision", + "path": "infra/relay/src/environments/EnvironmentLinker.ts", + "start": 227, + "end": 341, + "language": "typescript", + "label": "Relay challenge verification, replay defense, link, and endpoint provisioning", + "code": " const challenge = yield* relayTokens.verifyLinkChallenge({\n token: verified.challenge,\n userId: input.userId,\n request: {\n notificationsEnabled: input.request.notificationsEnabled,\n liveActivitiesEnabled: input.request.liveActivitiesEnabled,\n managedTunnelsEnabled: input.request.managedTunnelsEnabled,\n },\n nowEpochSeconds: nowSeconds,\n });\n if (challenge === null) {\n return yield* new EnvironmentLinkProofInvalid({\n userId: input.userId,\n environmentId: verified.environmentId,\n reason: \"challenge_invalid\",\n stage: \"verify_challenge\",\n });\n }\n const expiresAt = DateTime.make(verified.exp * 1_000);\n if (expiresAt._tag === \"None\") {\n return yield* new EnvironmentLinkProofInvalid({\n userId: input.userId,\n environmentId: verified.environmentId,\n reason: \"invalid_signature_or_scope\",\n stage: \"validate_expiration\",\n });\n }\n const consumedNonce = yield* proofReplay.consume({\n thumbprint: verified.environmentPublicKey,\n jti: verified.jti,\n iat: verified.iat,\n expiresAt: expiresAt.value,\n });\n if (!consumedNonce) {\n return yield* new EnvironmentLinkProofInvalid({\n userId: input.userId,\n environmentId: verified.environmentId,\n reason: \"replayed_nonce\",\n stage: \"consume_proof_nonce\",\n });\n }\n const consumedChallenge = yield* proofReplay.consume({\n thumbprint: \"relay-environment-link-challenge\",\n jti: challenge.jti,\n iat: challenge.iat,\n expiresAt: expiresAt.value,\n });\n if (!consumedChallenge) {\n return yield* new EnvironmentLinkProofInvalid({\n userId: input.userId,\n environmentId: verified.environmentId,\n reason: \"challenge_invalid\",\n stage: \"consume_challenge_nonce\",\n });\n }\n if (input.request.managedTunnelsEnabled && !isLoopbackManagedTunnelOrigin(verified.origin)) {\n return yield* new EnvironmentLinkProofInvalid({\n userId: input.userId,\n environmentId: verified.environmentId,\n reason: \"origin_not_allowed\",\n stage: \"validate_origin\",\n });\n }\n // Downgrading a managed link to publish-only must release the tunnel and\n // DNS that were provisioned for it — nothing else cleans them up until a\n // full unlink. Best effort: a cleanup failure must not block the link\n // itself, and the provider treats an absent allocation as already\n // deprovisioned, so retrying on every non-tunnel link is cheap.\n if (!input.request.managedTunnelsEnabled) {\n yield* managedEndpointProvider\n .deprovision({\n userId: input.userId,\n environmentId: verified.environmentId,\n })\n .pipe(\n Effect.tapError((error) =>\n Effect.logWarning(\"managed endpoint deprovision on publish-only link failed\", {\n environmentId: verified.environmentId,\n errorTag: error._tag,\n }),\n ),\n Effect.ignore,\n );\n }\n const provisioned = input.request.managedTunnelsEnabled\n ? yield* managedEndpointProvider.provision({\n userId: input.userId,\n environmentId: verified.environmentId,\n origin: verified.origin,\n })\n : null;\n const endpoint = provisioned?.endpoint ?? verified.endpoint;\n // The secure-endpoint requirement only matters when the relay advertises\n // this endpoint for other devices to reach (managed tunnel). Publish-only\n // links are reached out of band (e.g. Tailscale) and their stored endpoint\n // is never used for routing, so a nominal endpoint is acceptable.\n if (input.request.managedTunnelsEnabled && !isSecureManagedEndpoint(endpoint)) {\n return yield* new EnvironmentLinkProofInvalid({\n userId: input.userId,\n environmentId: verified.environmentId,\n reason: \"endpoint_not_secure\",\n stage: \"validate_endpoint\",\n });\n }\n yield* links.upsert({ ...input, proof: verified, endpoint });\n const environmentCredential = yield* credentials.create({\n environmentId: verified.environmentId,\n environmentPublicKey: verified.environmentPublicKey,\n });\n return {\n environmentId: verified.environmentId,\n endpoint,\n endpointRuntime: provisioned?.runtime ?? null,\n environmentCredential,\n };", + "checksum": "34db35e5e050fa71891b31226f004cdc587587676000e7a21ed897494fe0fcf0" + }, + "connect-managed-tunnel-provision": { + "id": "connect-managed-tunnel-provision", + "path": "infra/relay/src/environments/ManagedEndpointProvider.ts", + "start": 604, + "end": 855, + "language": "typescript", + "label": "Cloudflare tunnel allocation, ingress, DNS, and connector runtime", + "code": " provision: Effect.fn(\"relay.managed_endpoint_provider.provision\")(function* (input) {\n yield* Effect.annotateCurrentSpan({\n \"relay.user_id\": input.userId,\n \"relay.environment_id\": input.environmentId,\n \"relay.managed_endpoint.origin_host\": input.origin.localHttpHost,\n \"relay.managed_endpoint.origin_port\": input.origin.localHttpPort,\n });\n if (!isLoopbackOrigin(input.origin)) {\n return yield* new ManagedEndpointOriginNotAllowed({\n userId: input.userId,\n environmentId: input.environmentId,\n host: input.origin.localHttpHost,\n port: input.origin.localHttpPort,\n });\n }\n const cf = yield* requireCloudflareSettings(config, input);\n const environmentHash = yield* crypto\n .digest(\n \"SHA-256\",\n new TextEncoder().encode(\n managedEndpointDigestInput(cf.namespace, input.userId, input.environmentId),\n ),\n )\n .pipe(\n Effect.map(Encoding.encodeHex),\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"derive-environment-hash\",\n cause,\n }),\n ),\n );\n const requestedHostname = managedEndpointHostname(\n cf.namespace,\n cf.baseDomain,\n environmentHash,\n );\n const requestedTunnelName = managedEndpointTunnelName(cf.namespace, environmentHash);\n yield* tunnelLimits\n .ensureCapacity({\n userId: input.userId,\n environmentId: input.environmentId,\n })\n .pipe(\n Effect.catchTags({\n ManagedTunnelLimitPersistenceError: (cause) =>\n Effect.fail(\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"check-tunnel-limit\",\n hostname: requestedHostname,\n tunnelName: requestedTunnelName,\n cause,\n }),\n ),\n }),\n );\n const allocation = yield* allocations\n .reserve({\n userId: input.userId,\n environmentId: input.environmentId,\n hostname: requestedHostname,\n tunnelName: requestedTunnelName,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"reserve-allocation\",\n hostname: requestedHostname,\n tunnelName: requestedTunnelName,\n cause,\n }),\n ),\n );\n const { hostname, tunnelName } = allocation;\n\n const tunnelResponse = yield* tunnels.list({ name: tunnelName, isDeleted: false }).pipe(\n Effect.map((tunnels) => tunnels.result),\n Effect.map(Arr.findFirst((tunnel) => tunnel.name === tunnelName)),\n Effect.flatMap(\n Option.match({\n onSome: (tunnel) => Effect.succeed(tunnel),\n onNone: () => tunnels.create({ name: tunnelName, configSrc: \"cloudflare\" }),\n }),\n ),\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"ensure-tunnel\",\n hostname,\n tunnelName,\n cause,\n }),\n ),\n );\n if (!tunnelResponse.id || tunnelResponse.name !== tunnelName) {\n return yield* new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"validate-tunnel-response\",\n hostname,\n tunnelName,\n ...(tunnelResponse.id ? { returnedTunnelId: tunnelResponse.id } : {}),\n ...(tunnelResponse.name ? { returnedTunnelName: tunnelResponse.name } : {}),\n });\n }\n const tunnel = { id: tunnelResponse.id, name: tunnelResponse.name };\n yield* allocations\n .recordTunnel({\n userId: input.userId,\n environmentId: input.environmentId,\n tunnelId: tunnel.id,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"record-tunnel\",\n hostname,\n tunnelName,\n tunnelId: tunnel.id,\n cause,\n }),\n ),\n );\n\n yield* tunnels\n .putConfiguration(tunnel.id, {\n ingress: [\n {\n hostname,\n service: formatOriginService(input.origin),\n },\n { service: \"http_status:404\" },\n ],\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"configure-tunnel\",\n hostname,\n tunnelName,\n tunnelId: tunnel.id,\n cause,\n }),\n ),\n );\n\n const dnsRecord = {\n type: \"CNAME\",\n name: hostname,\n content: `${tunnel.id}.cfargotunnel.com`,\n ttl: 1,\n proxied: true,\n } as const;\n\n const dnsRecordId = yield* ensureDnsRecord(hostname, allocation.dnsRecordId, dnsRecord).pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"ensure-dns-record\",\n hostname,\n tunnelName,\n tunnelId: tunnel.id,\n ...(allocation.dnsRecordId === null ? {} : { dnsRecordId: allocation.dnsRecordId }),\n cause,\n }),\n ),\n );\n yield* allocations\n .recordDns({\n userId: input.userId,\n environmentId: input.environmentId,\n dnsRecordId,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"record-dns\",\n hostname,\n tunnelName,\n tunnelId: tunnel.id,\n dnsRecordId,\n cause,\n }),\n ),\n );\n\n const connectorToken = yield* tunnels.getToken(tunnel.id).pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"get-tunnel-token\",\n hostname,\n tunnelName,\n tunnelId: tunnel.id,\n dnsRecordId,\n cause,\n }),\n ),\n );\n yield* allocations\n .markReady({\n userId: input.userId,\n environmentId: input.environmentId,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new ManagedEndpointProvisioningFailed({\n userId: input.userId,\n environmentId: input.environmentId,\n stage: \"mark-allocation-ready\",\n hostname,\n tunnelName,\n tunnelId: tunnel.id,\n dnsRecordId,\n cause,\n }),\n ),\n );\n\n return {\n endpoint: managedEndpointForHostname(hostname),\n runtime: {\n providerKind: \"cloudflare_tunnel\",\n connectorToken,\n tunnelId: tunnel.id,\n tunnelName: tunnel.name,\n },\n } satisfies ManagedEndpointProvisioningResult;", + "checksum": "d9dfb0d6ddc6c065244090282008cc23ad237b8f854c37b6ae395981feaef571" + }, + "connect-environment-runtime-tunnel": { + "id": "connect-environment-runtime-tunnel", + "path": "apps/server/src/cloud/ManagedEndpointRuntime.ts", + "start": 187, + "end": 287, + "language": "typescript", + "label": "Environment-owned managed tunnel child supervision", + "code": " reconcileConfig = Effect.fn(\"CloudManagedEndpointRuntime.reconcileConfig\")(function* (config) {\n if (!config || config.providerKind !== \"cloudflare_tunnel\") {\n yield* stopActive;\n return config\n ? { status: \"unsupported\", providerKind: config.providerKind }\n : { status: \"disabled\" };\n }\n\n const nextConfigKey = runtimeConfigKey(config);\n const active = yield* Ref.get(activeRef);\n if (active?.configKey === nextConfigKey) {\n const isRunning = yield* active.child.isRunning.pipe(Effect.orElseSucceed(() => false));\n if (isRunning) {\n return {\n status: \"running\",\n providerKind: \"cloudflare_tunnel\",\n pid: Number(active.child.pid),\n ...(active.config.tunnelId ? { tunnelId: active.config.tunnelId } : {}),\n ...(active.config.tunnelName ? { tunnelName: active.config.tunnelName } : {}),\n } satisfies CloudManagedEndpointRuntimeStatus;\n }\n }\n\n yield* stopActive;\n\n const executable = yield* relayClient.resolve;\n if (executable.status !== \"available\") {\n return {\n status: \"failed\",\n providerKind: \"cloudflare_tunnel\",\n reason:\n executable.status === \"unsupported\"\n ? `Relay client is unsupported on ${executable.platform}-${executable.arch}.`\n : \"The relay client is not installed.\",\n ...(config.tunnelId ? { tunnelId: config.tunnelId } : {}),\n ...(config.tunnelName ? { tunnelName: config.tunnelName } : {}),\n } satisfies CloudManagedEndpointRuntimeStatus;\n }\n\n const connectorScope = yield* Scope.make(\"sequential\");\n const child = yield* spawner\n .spawn(\n ChildProcess.make(executable.executablePath, [\"tunnel\", \"run\"], {\n detached: false,\n env: {\n ...process.env,\n TUNNEL_TOKEN: config.connectorToken,\n },\n shell: false,\n stderr: \"pipe\",\n stdout: \"pipe\",\n }),\n )\n .pipe(\n Effect.provideService(Scope.Scope, connectorScope),\n Effect.tap((child) =>\n Effect.logInfo(\"Relay client process started; waiting for tunnel connection\", {\n pid: Number(child.pid),\n tunnelId: config.tunnelId,\n tunnelName: config.tunnelName,\n }),\n ),\n Effect.catch((cause) =>\n Effect.logWarning(\"Failed to start relay client\", {\n cause,\n tunnelId: config.tunnelId,\n tunnelName: config.tunnelName,\n }).pipe(\n Effect.andThen(Scope.close(connectorScope, Exit.void).pipe(Effect.ignore)),\n Effect.as({\n status: \"failed\",\n providerKind: \"cloudflare_tunnel\",\n reason: String(cause),\n ...(config.tunnelId ? { tunnelId: config.tunnelId } : {}),\n ...(config.tunnelName ? { tunnelName: config.tunnelName } : {}),\n } satisfies CloudManagedEndpointRuntimeStatus),\n ),\n ),\n );\n\n if (\"status\" in child && child.status === \"failed\") {\n return child;\n }\n\n if (!(\"status\" in child)) {\n const connector = {\n child,\n scope: connectorScope,\n configKey: nextConfigKey,\n config,\n } satisfies ActiveConnector;\n yield* Ref.set(activeRef, connector);\n yield* Effect.forkIn(observeConnectorOutput(connector), connectorScope);\n yield* Effect.forkIn(superviseConnector(connector), connectorScope);\n return {\n status: \"running\",\n providerKind: \"cloudflare_tunnel\",\n pid: Number(child.pid),\n ...(config.tunnelId ? { tunnelId: config.tunnelId } : {}),\n ...(config.tunnelName ? { tunnelName: config.tunnelName } : {}),\n } satisfies CloudManagedEndpointRuntimeStatus;", + "checksum": "15a5736f8e3481d7117acb0331cf0d9969a2bf86bf2755734a1f3af6036df8b2" + }, + "connect-relay-environment-mint": { + "id": "connect-relay-environment-mint", + "path": "infra/relay/src/environments/EnvironmentConnector.ts", + "start": 541, + "end": 670, + "language": "typescript", + "label": "Proof-key-bound relay mint request and environment bootstrap credential", + "code": " connect: Effect.fn(\"relay.environment_connector.connect\")(function* (input) {\n yield* Effect.annotateCurrentSpan({\n \"relay.environment_id\": input.environmentId,\n \"relay.operation\": \"connect\",\n \"relay.connect.has_device_id\": input.deviceId !== undefined,\n ...(input.deviceId ? { \"relay.mobile.device_id\": input.deviceId } : {}),\n });\n if (input.clientProofKeyThumbprint.trim().length === 0) {\n return yield* new EnvironmentConnectNotAuthorized({\n environmentId: input.environmentId,\n operation: \"connect\",\n reason: \"client_proof_key_thumbprint_missing\",\n });\n }\n const { link, allocation } = yield* Effect.all(\n {\n link: links.getForUser(input),\n allocation: allocations.get(input),\n },\n { concurrency: 2 },\n );\n if (!link) {\n return yield* new EnvironmentConnectNotAuthorized({\n environmentId: input.environmentId,\n operation: \"connect\",\n reason: \"environment_link_not_found\",\n });\n }\n const endpoint = yield* resolveManagedEndpoint({\n operation: \"connect\",\n link,\n allocation,\n });\n const now = yield* DateTime.now;\n const expiresAt = DateTime.add(now, { minutes: 2 });\n const nonce = yield* crypto.randomUUIDv4.pipe(\n Effect.mapError(\n (cause) =>\n new EnvironmentMintRequestFailed({\n environmentId: input.environmentId,\n operation: \"connect\",\n cause,\n }),\n ),\n );\n const payload = {\n iss: relayIssuer,\n aud: `t3-env:${link.environmentId}`,\n sub: input.userId,\n jti: yield* crypto.randomUUIDv4.pipe(\n Effect.mapError(\n (cause) =>\n new EnvironmentMintRequestFailed({\n environmentId: input.environmentId,\n operation: \"connect\",\n cause,\n }),\n ),\n ),\n iat: Math.floor(now.epochMilliseconds / 1_000),\n exp: Math.floor(expiresAt.epochMilliseconds / 1_000),\n environmentId: link.environmentId,\n clientProofKeyThumbprint: input.clientProofKeyThumbprint,\n cnf: { jkt: input.clientProofKeyThumbprint },\n ...(input.deviceId ? { deviceId: input.deviceId } : {}),\n nonce,\n scope: [\"environment:connect\"],\n } satisfies RelayCloudMintCredentialProofPayload;\n const proof = yield* signRelayJwt({\n privateKey: Redacted.value(settings.cloudMintPrivateKey),\n typ: RELAY_MINT_REQUEST_TYP,\n payload,\n }).pipe(\n Effect.mapError(\n (cause) =>\n new EnvironmentMintRequestFailed({\n environmentId: input.environmentId,\n operation: \"connect\",\n cause,\n }),\n ),\n );\n const environmentClient = yield* makeEnvironmentClient(endpoint.httpBaseUrl);\n const decoded = yield* environmentClient.connect\n .t3MintCredential({ payload: { proof } })\n .pipe(\n withoutRedirects,\n Effect.mapError(\n (cause) =>\n new EnvironmentMintRequestFailed({\n environmentId: input.environmentId,\n operation: \"connect\",\n cause,\n }),\n ),\n Effect.timeoutOption(Duration.millis(ENVIRONMENT_MINT_REQUEST_TIMEOUT_MS)),\n Effect.flatMap(\n Option.match({\n onNone: () =>\n Effect.fail(\n new EnvironmentMintRequestTimedOut({\n environmentId: input.environmentId,\n timeoutMs: ENVIRONMENT_MINT_REQUEST_TIMEOUT_MS,\n }),\n ),\n onSome: Effect.succeed,\n }),\n ),\n );\n const verified = yield* verifyEnvironmentResponse({\n response: decoded,\n environmentId: input.environmentId,\n requestNonce: nonce,\n clientProofKeyThumbprint: input.clientProofKeyThumbprint,\n environmentPublicKeys: [link.environmentPublicKey],\n relayIssuer,\n nowEpochSeconds: Math.floor(now.epochMilliseconds / 1_000),\n });\n if (!verified) {\n return yield* new EnvironmentMintResponseInvalid({\n environmentId: input.environmentId,\n operation: \"connect\",\n });\n }\n return {\n environmentId: link.environmentId,\n endpoint,\n credential: decoded.credential,\n expiresAt: decoded.expiresAt,\n };", + "checksum": "87e768757d71f7890b3a25324faae60572ccb16545a28d7fe42df583c9eebd6b" + }, + "dpop-validation": { + "id": "dpop-validation", + "path": "packages/shared/src/dpop.ts", + "start": 1, + "end": 175, + "language": "typescript", + "label": "DPoP signature, target, token hash, and time validation", + "code": "import { p256 } from \"@noble/curves/nist\";\nimport { sha256 } from \"@noble/hashes/sha2\";\nimport * as Encoding from \"effect/Encoding\";\nimport * as Option from \"effect/Option\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\n\nimport { DpopPublicJwk as DpopPublicJwkSchema, normalizeDpopHtu } from \"./dpopCommon.ts\";\nimport type { DpopPublicJwk as DpopPublicJwkType } from \"./dpopCommon.ts\";\nimport { stableStringify } from \"./relaySigning.ts\";\n\nconst DPOP_TYP = \"dpop+jwt\";\nconst DPOP_ALG = \"ES256\";\nconst DEFAULT_MAX_AGE_SECONDS = 300;\n\nexport const DpopPublicJwk = DpopPublicJwkSchema;\nexport type DpopPublicJwk = DpopPublicJwkType;\nexport { normalizeDpopHtu };\n\nconst DpopJwtHeaderPublicJwk = Schema.Struct({\n ...DpopPublicJwkSchema.fields,\n d: Schema.optionalKey(Schema.Never),\n});\n\nconst DpopJwtHeaderJson = Schema.fromJsonString(\n Schema.Struct({\n typ: Schema.Literal(DPOP_TYP),\n alg: Schema.Literal(DPOP_ALG),\n jwk: DpopJwtHeaderPublicJwk,\n }),\n);\nconst decodeDpopJwtHeaderJson = Schema.decodeUnknownOption(DpopJwtHeaderJson);\n\nconst DpopJwtPayloadJson = Schema.fromJsonString(\n Schema.Struct({\n htm: Schema.String.check(Schema.isNonEmpty()),\n htu: Schema.String.check(Schema.isNonEmpty()),\n jti: Schema.String.check(Schema.isNonEmpty()),\n iat: Schema.Int,\n ath: Schema.optionalKey(Schema.String),\n }),\n);\nconst decodeDpopJwtPayloadJson = Schema.decodeUnknownOption(DpopJwtPayloadJson);\n\nexport type DpopVerificationResult =\n | {\n readonly ok: true;\n readonly thumbprint: string;\n readonly jti: string;\n readonly iat: number;\n }\n | {\n readonly ok: false;\n readonly reason: string;\n };\n\nfunction base64UrlToBytes(value: string): Uint8Array {\n return Result.getOrThrow(Encoding.decodeBase64Url(value));\n}\n\nfunction decodeBase64UrlDpopJwtHeader(value: string) {\n return decodeDpopJwtHeaderJson(Result.getOrThrow(Encoding.decodeBase64UrlString(value)));\n}\n\nfunction decodeBase64UrlDpopJwtPayload(value: string) {\n return decodeDpopJwtPayloadJson(Result.getOrThrow(Encoding.decodeBase64UrlString(value)));\n}\n\nfunction dpopThumbprintInput(jwk: DpopPublicJwkType): string {\n return stableStringify({\n crv: jwk.crv,\n kty: jwk.kty,\n x: jwk.x,\n y: jwk.y,\n });\n}\n\nexport function computeDpopJwkThumbprint(jwk: DpopPublicJwkType): string {\n return Encoding.encodeBase64Url(sha256(new TextEncoder().encode(dpopThumbprintInput(jwk))));\n}\n\nexport function computeDpopAccessTokenHash(accessToken: string): string {\n return Encoding.encodeBase64Url(sha256(new TextEncoder().encode(accessToken)));\n}\n\nfunction publicKeyBytesFromJwk(jwk: DpopPublicJwkType): Uint8Array {\n const x = base64UrlToBytes(jwk.x);\n const y = base64UrlToBytes(jwk.y);\n if (x.length !== 32 || y.length !== 32) {\n throw new Error(\"Invalid P-256 public key coordinate length.\");\n }\n const publicKey = new Uint8Array(65);\n publicKey[0] = 0x04;\n publicKey.set(x, 1);\n publicKey.set(y, 33);\n return publicKey;\n}\n\nexport function verifyDpopProof(input: {\n readonly proof: string | null | undefined;\n readonly method: string;\n readonly url: string;\n readonly nowEpochSeconds: number;\n readonly expectedThumbprint?: string;\n readonly expectedAccessToken?: string;\n readonly maxAgeSeconds?: number;\n}): DpopVerificationResult {\n if (!input.proof?.trim()) {\n return { ok: false, reason: \"Missing DPoP proof.\" };\n }\n\n const parts = input.proof.split(\".\");\n if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2]) {\n return { ok: false, reason: \"Invalid DPoP compact JWT.\" };\n }\n\n try {\n const header = decodeBase64UrlDpopJwtHeader(parts[0]);\n const payload = decodeBase64UrlDpopJwtPayload(parts[1]);\n if (Option.isNone(header)) {\n return { ok: false, reason: \"Invalid DPoP JWT header.\" };\n }\n if (Option.isNone(payload)) {\n return { ok: false, reason: \"Invalid DPoP JWT payload.\" };\n }\n\n const thumbprint = computeDpopJwkThumbprint(header.value.jwk);\n if (input.expectedThumbprint && thumbprint !== input.expectedThumbprint) {\n return { ok: false, reason: \"DPoP key thumbprint mismatch.\" };\n }\n if (payload.value.htm.toUpperCase() !== input.method.toUpperCase()) {\n return { ok: false, reason: \"DPoP method mismatch.\" };\n }\n const normalizedHtu = normalizeDpopHtu(input.url);\n if (normalizedHtu === null || payload.value.htu !== normalizedHtu) {\n return { ok: false, reason: \"DPoP URL mismatch.\" };\n }\n if (input.expectedAccessToken) {\n const expectedAth = computeDpopAccessTokenHash(input.expectedAccessToken);\n if (payload.value.ath !== expectedAth) {\n return { ok: false, reason: \"DPoP access token hash mismatch.\" };\n }\n }\n\n const maxAgeSeconds = input.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS;\n if (\n payload.value.iat > input.nowEpochSeconds + 5 ||\n input.nowEpochSeconds - payload.value.iat > maxAgeSeconds\n ) {\n return { ok: false, reason: \"DPoP proof is outside the allowed time window.\" };\n }\n\n const signature = base64UrlToBytes(parts[2]);\n const signatureInputHash = sha256(new TextEncoder().encode(`${parts[0]}.${parts[1]}`));\n const verified = p256.verify(\n signature,\n signatureInputHash,\n publicKeyBytesFromJwk(header.value.jwk),\n {\n prehash: false,\n format: \"compact\",\n },\n );\n return verified\n ? {\n ok: true,\n thumbprint,\n jti: payload.value.jti,\n iat: payload.value.iat,\n }\n : { ok: false, reason: \"Invalid DPoP signature.\" };\n } catch {\n return { ok: false, reason: \"Invalid DPoP proof.\" };\n }\n}", + "checksum": "a201cbe8739a6da8f782df3f52c70e27b8ff61b5dcdf9de50075955966c8bf43" + }, + "managed-relay-dpop-authorization": { + "id": "managed-relay-dpop-authorization", + "path": "packages/client-runtime/src/authorization/service.ts", + "start": 180, + "end": 299, + "language": "typescript", + "label": "Managed relay bootstrap becomes a distinct DPoP-bound environment session", + "code": " const authorizeDpop = Effect.fn(\"clientRuntime.connection.remote.authorizeDpop\")(\n function* (input: {\n readonly expectedEnvironmentId: Parameters<\n RemoteEnvironmentAuthorization[\"Service\"][\"authorizeDpop\"]\n >[0][\"expectedEnvironmentId\"];\n readonly obtainBootstrap: Parameters<\n RemoteEnvironmentAuthorization[\"Service\"][\"authorizeDpop\"]\n >[0][\"obtainBootstrap\"];\n }) {\n const thumbprint = yield* signer.thumbprint.pipe(\n Effect.mapError(\n () =>\n new ConnectionBlockedError({\n reason: \"configuration\",\n detail: \"Could not load the environment authorization key.\",\n }),\n ),\n Effect.withSpan(\"environment.authorization.dpopKey.resolve\"),\n );\n const now = yield* Clock.currentTimeMillis;\n const cached = yield* tokenStore\n .get(input.expectedEnvironmentId)\n .pipe(Effect.withSpan(\"environment.authorization.accessToken.cache\"));\n if (\n Option.isSome(cached) &&\n cached.value.environmentId === input.expectedEnvironmentId &&\n cached.value.dpopThumbprint === thumbprint &&\n cached.value.expiresAtEpochMs > now + TOKEN_EXPIRY_SAFETY_MARGIN_MS\n ) {\n yield* Effect.annotateCurrentSpan({\n \"connection.remote_token_cache\": \"hit\",\n });\n const cachedSocket = yield* createDpopSocketUrl(\n cached.value,\n CACHED_ENDPOINT_SOCKET_TIMEOUT_MS,\n ).pipe(Effect.result);\n if (Result.isSuccess(cachedSocket)) {\n return {\n environmentId: cached.value.environmentId,\n label: cached.value.label,\n httpBaseUrl: cached.value.endpoint.httpBaseUrl,\n socketUrl: cachedSocket.success,\n httpAuthorization: {\n _tag: \"Dpop\" as const,\n accessToken: cached.value.accessToken,\n },\n };\n }\n if (cachedSocket.failure._tag === \"ConnectionBlockedError\") {\n return yield* mapDpopSocketError(cachedSocket.failure);\n }\n yield* tokenStore\n .remove(input.expectedEnvironmentId)\n .pipe(Effect.withSpan(\"environment.authorization.accessToken.remove\"));\n }\n\n yield* Effect.annotateCurrentSpan({\n \"connection.remote_token_cache\": \"miss\",\n });\n const bootstrap = yield* input.obtainBootstrap;\n const descriptor = yield* fetchDescriptor(bootstrap.endpoint.httpBaseUrl).pipe(\n Effect.provideService(HttpClient.HttpClient, httpClient),\n Effect.withSpan(\"environment.authorization.descriptor\"),\n );\n if (descriptor.environmentId !== input.expectedEnvironmentId) {\n return yield* environmentMismatchError({\n expected: input.expectedEnvironmentId,\n actual: descriptor.environmentId,\n });\n }\n const bootstrapProof = yield* signer\n .createProof({\n method: \"POST\",\n url: environmentEndpointUrl(bootstrap.endpoint.httpBaseUrl, \"/oauth/token\"),\n })\n .pipe(\n Effect.mapError(\n () =>\n new ConnectionBlockedError({\n reason: \"configuration\",\n detail: \"Could not create the environment authorization proof.\",\n }),\n ),\n );\n const access = yield* exchangeRemoteDpopAccessToken({\n httpBaseUrl: bootstrap.endpoint.httpBaseUrl,\n credential: bootstrap.credential,\n dpopProof: bootstrapProof,\n scopes: presentation.scopes,\n clientMetadata: presentation.metadata,\n }).pipe(\n Effect.mapError(mapRemoteEnvironmentError),\n Effect.provideService(HttpClient.HttpClient, httpClient),\n Effect.withSpan(\"environment.authorization.accessToken.exchange\"),\n );\n const issuedAt = yield* Clock.currentTimeMillis;\n const token = new TokenStore.RemoteDpopAccessToken({\n environmentId: descriptor.environmentId,\n label: descriptor.label,\n endpoint: bootstrap.endpoint,\n accessToken: access.access_token,\n expiresAtEpochMs: issuedAt + access.expires_in * 1_000,\n dpopThumbprint: thumbprint,\n });\n const socketUrl = yield* createDpopSocketUrl(token).pipe(Effect.mapError(mapDpopSocketError));\n yield* tokenStore\n .put(token)\n .pipe(Effect.withSpan(\"environment.authorization.accessToken.persist\"));\n return {\n environmentId: descriptor.environmentId,\n label: descriptor.label,\n httpBaseUrl: bootstrap.endpoint.httpBaseUrl,\n socketUrl,\n httpAuthorization: {\n _tag: \"Dpop\" as const,\n accessToken: token.accessToken,\n },\n };\n },\n );", + "checksum": "6815918aa0e64771f373da90aa947033e4b180c8a4d9c6308afdacebd6880dbb" + }, + "reconnect-environment-registry": { + "id": "reconnect-environment-registry", + "path": "packages/client-runtime/src/connection/registry.ts", + "start": 156, + "end": 289, + "language": "typescript", + "label": "Environment-scoped runtime registry and lease replacement", + "code": " const entries =\n yield* SubscriptionRef.make>(initialEntries);\n const networkStatus = yield* SubscriptionRef.make(yield* connectivity.status);\n const serviceScopes = yield* SubscriptionRef.make<\n ReadonlyMap\n >(new Map());\n const platformEnvironmentIds = yield* Ref.make>(new Set());\n const persistedTargetsByEnvironment = yield* Ref.make<\n ReadonlyMap\n >(new Map(persistedTargets.map((target) => [target.environmentId, target])));\n interface LeaseLock {\n readonly semaphore: Semaphore.Semaphore;\n readonly users: number;\n }\n\n const leaseLocks = yield* Ref.make>(new Map());\n const leaseLocksGuard = yield* Semaphore.make(1);\n const started = yield* Ref.make(false);\n\n const withLeaseLock = (\n environmentId: EnvironmentId,\n effect: Effect.Effect,\n ): Effect.Effect =>\n Effect.acquireUseRelease(\n leaseLocksGuard.withPermits(1)(\n Effect.gen(function* () {\n const current = yield* Ref.get(leaseLocks);\n const existing = current.get(environmentId);\n if (existing !== undefined) {\n yield* Ref.set(\n leaseLocks,\n new Map(current).set(environmentId, {\n semaphore: existing.semaphore,\n users: existing.users + 1,\n }),\n );\n return existing.semaphore;\n }\n const semaphore = yield* Semaphore.make(1);\n yield* Ref.set(leaseLocks, new Map(current).set(environmentId, { semaphore, users: 1 }));\n return semaphore;\n }),\n ),\n (semaphore) => semaphore.withPermits(1)(effect),\n (semaphore) =>\n leaseLocksGuard.withPermits(1)(\n Ref.update(leaseLocks, (current) => {\n const existing = current.get(environmentId);\n if (existing === undefined || existing.semaphore !== semaphore) {\n return current;\n }\n const next = new Map(current);\n if (existing.users === 1) {\n next.delete(environmentId);\n } else {\n next.set(environmentId, {\n semaphore,\n users: existing.users - 1,\n });\n }\n return next;\n }),\n ),\n ).pipe(Effect.withSpan(\"EnvironmentRegistry.withLeaseLock\"));\n\n const getEntry = Effect.fn(\"EnvironmentRegistry.getEntry\")(function* (\n environmentId: EnvironmentId,\n ) {\n const entry = (yield* SubscriptionRef.get(entries)).get(environmentId);\n if (entry === undefined) {\n return yield* new EnvironmentNotRegisteredError({\n environmentId,\n });\n }\n return entry;\n });\n\n const closeServiceScope = Effect.fn(\"EnvironmentRegistry.closeServiceScope\")(function* (\n environmentId: EnvironmentId,\n ) {\n const current = yield* SubscriptionRef.get(serviceScopes);\n const lease = current.get(environmentId);\n if (lease === undefined) {\n return;\n }\n const next = new Map(current);\n next.delete(environmentId);\n yield* SubscriptionRef.set(serviceScopes, next);\n yield* Scope.close(lease.scope, Exit.void);\n });\n\n const createServiceScope = Effect.fn(\"EnvironmentRegistry.createServiceScope\")(\n (entry: ConnectionCatalogEntry) =>\n Effect.uninterruptible(\n Effect.gen(function* () {\n const environmentId = entry.target.environmentId;\n const scope = yield* Scope.make();\n const supervisor = yield* EnvironmentSupervisor.make(entry, {\n initiallyDesired: false,\n }).pipe(\n Effect.provideService(Connectivity.Connectivity, connectivity),\n Effect.provideService(ConnectionDriver.ConnectionDriver, driver),\n Effect.provideService(ConnectionWakeups.ConnectionWakeups, wakeups),\n Scope.provide(scope),\n Effect.onError(() => Scope.close(scope, Exit.void)),\n );\n yield* supervisor.connect;\n yield* SubscriptionRef.update(serviceScopes, (current) => {\n const next = new Map(current);\n next.set(environmentId, { entry, supervisor, scope });\n return next;\n });\n return supervisor;\n }),\n ),\n );\n\n const acquireSupervisor = Effect.fn(\"EnvironmentRegistry.acquireSupervisor\")(function* (\n environmentId: EnvironmentId,\n ) {\n return yield* withLeaseLock(\n environmentId,\n Effect.gen(function* () {\n const entry = yield* getEntry(environmentId);\n const existing = (yield* SubscriptionRef.get(serviceScopes)).get(environmentId);\n if (existing !== undefined) {\n if (Equal.equals(existing.entry, entry)) {\n return existing.supervisor;\n }\n yield* closeServiceScope(environmentId);\n }\n return yield* createServiceScope(entry);\n }),\n );", + "checksum": "12b74a7bf02c25c818e09218075f7ada2c45fbc08ff74ec48531c05611264fd3" + }, + "reconnect-scoped-environment-refs": { + "id": "reconnect-scoped-environment-refs", + "path": "packages/contracts/src/environment.ts", + "start": 31, + "end": 130, + "language": "typescript", + "label": "Environment descriptors and scoped project and thread references", + "code": "/** How a server can replace itself with another version when asked over RPC.\n New servers only advertise the stable launcher-backed \"boot-service\" path;\n \"respawn\" remains decodable for compatibility with older servers. */\nexport const ServerSelfUpdateMethod = Schema.Literals([\"boot-service\", \"respawn\"]);\nexport type ServerSelfUpdateMethod = typeof ServerSelfUpdateMethod.Type;\n\n/** What update path a client should offer for a server: one of the RPC\n self-update methods above, or \"desktop-managed\" when the backend's\n version belongs to the T3 Code desktop app supervising it — updating the\n app on that machine is the only way to update the server. */\nexport const ServerSelfUpdateCapability = Schema.Literals([\n \"boot-service\",\n \"respawn\",\n \"desktop-managed\",\n]);\nexport type ServerSelfUpdateCapability = typeof ServerSelfUpdateCapability.Type;\n\nexport const ExecutionEnvironmentCapabilities = Schema.Struct({\n repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),\n connectionProbe: Schema.optionalKey(Schema.Boolean),\n /** Server exposes the pull-request list, detail, activity, diff, and mutation APIs. Absent on\n servers from before the pull-request workspace shipped, so clients must not probe them. */\n pullRequests: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.settle / thread.unsettle commands. Absent on\n pre-settlement servers, so clients treat missing as unsupported and\n never send the commands under version skew. */\n threadSettlement: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.snooze / thread.unsnooze commands. Same\n version-skew contract as threadSettlement. */\n threadSnooze: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.pin / thread.unpin commands. Same\n version-skew contract as threadSettlement. */\n threadPinning: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.pin.reorder (and orderKey on thread.pin).\n Same version-skew contract as threadSettlement. */\n threadPinReorder: Schema.optionalKey(Schema.Boolean),\n /** Server understands regenerateTitle on thread.meta.update. Absent on\n older servers, so clients hide the action instead of sending it. */\n threadTitleRegeneration: Schema.optionalKey(Schema.Boolean),\n /** The update path clients should offer for this server. Absent on\n servers that must be relaunched manually (dev checkouts, Windows\n foreground runs, pre-update servers). */\n serverSelfUpdate: Schema.optionalKey(ServerSelfUpdateCapability),\n /** Server can stream self-update progress before acknowledging the\n restart. Clients fall back to server.updateServer when absent. */\n serverSelfUpdateProgress: Schema.optionalKey(Schema.Boolean),\n /** Agent-activity publishes (push notifications and Live Activities)\n currently leave this environment: the publish opt-in is enabled and the\n relay link credentials exist. Clients skip seeding a Live Activity when\n this is false — no update would ever repaint it. Absent on older\n servers, which may still publish, so only an explicit false skips. */\n agentActivityPublishing: Schema.optionalKey(Schema.Boolean),\n});\nexport type ExecutionEnvironmentCapabilities = typeof ExecutionEnvironmentCapabilities.Type;\n\nexport const ExecutionEnvironmentDescriptor = Schema.Struct({\n environmentId: EnvironmentId,\n label: TrimmedNonEmptyString,\n platform: ExecutionEnvironmentPlatform,\n serverVersion: TrimmedNonEmptyString,\n capabilities: ExecutionEnvironmentCapabilities,\n});\nexport type ExecutionEnvironmentDescriptor = typeof ExecutionEnvironmentDescriptor.Type;\n\nexport const EnvironmentConnectionState = Schema.Literals([\n \"connecting\",\n \"connected\",\n \"disconnected\",\n \"error\",\n]);\nexport type EnvironmentConnectionState = typeof EnvironmentConnectionState.Type;\n\nexport const RepositoryIdentityLocator = Schema.Struct({\n source: Schema.Literal(\"git-remote\"),\n remoteName: TrimmedNonEmptyString,\n remoteUrl: TrimmedNonEmptyString,\n});\nexport type RepositoryIdentityLocator = typeof RepositoryIdentityLocator.Type;\n\nexport const RepositoryIdentity = Schema.Struct({\n canonicalKey: TrimmedNonEmptyString,\n locator: RepositoryIdentityLocator,\n rootPath: Schema.optionalKey(TrimmedNonEmptyString),\n displayName: Schema.optionalKey(TrimmedNonEmptyString),\n provider: Schema.optionalKey(TrimmedNonEmptyString),\n owner: Schema.optionalKey(TrimmedNonEmptyString),\n name: Schema.optionalKey(TrimmedNonEmptyString),\n});\nexport type RepositoryIdentity = typeof RepositoryIdentity.Type;\n\nexport const ScopedProjectRef = Schema.Struct({\n environmentId: EnvironmentId,\n projectId: ProjectId,\n});\nexport type ScopedProjectRef = typeof ScopedProjectRef.Type;\n\nexport const ScopedThreadRef = Schema.Struct({\n environmentId: EnvironmentId,\n threadId: ThreadId,\n});", + "checksum": "8adc3eeb2048647115e388b4fc57aea27ff94e4eeb613ad4a0bd5727d0c63d7e" + }, + "reconnect-supervisor-active-lease": { + "id": "reconnect-supervisor-active-lease", + "path": "packages/client-runtime/src/connection/supervisor.ts", + "start": 490, + "end": 615, + "language": "typescript", + "label": "Active prepared connection and RPC session lease lifecycle", + "code": " const runAttempt = Effect.fnUntraced(function* (\n attempt: number,\n generation: number,\n lastFailure: ConnectionAttemptError | null,\n pendingRetry: Option.Option,\n ) {\n yield* SubscriptionRef.set(prepared, Option.none());\n const establishment = yield* Effect.raceAllFirst([\n exitUnlessInterrupted(\n establishTracedConnection(attempt, generation, lastFailure, pendingRetry),\n ).pipe(\n Effect.map(\n (exit): EstablishmentEvent => ({\n _tag: \"Completed\",\n exit,\n }),\n ),\n ),\n waitForEstablishmentInterrupt().pipe(\n Effect.map(\n (resetRetry): EstablishmentEvent => ({\n _tag: \"Interrupted\",\n resetRetry,\n }),\n ),\n ),\n Effect.sleep(CONNECTION_ESTABLISHMENT_TIMEOUT).pipe(\n Effect.as({ _tag: \"TimedOut\" }),\n ),\n ]);\n\n if (establishment._tag === \"Interrupted\") {\n return {\n _tag: \"Interrupted\",\n established: false,\n stable: false,\n resetRetry: establishment.resetRetry,\n } satisfies AttemptOutcome;\n }\n if (establishment._tag === \"TimedOut\") {\n return {\n _tag: \"Failure\",\n established: false,\n stable: false,\n failure: {\n error: new ConnectionTransientError({\n reason: \"timeout\",\n detail: `${target.label} did not respond during connection setup.`,\n }),\n attemptSpan: Option.none(),\n },\n } satisfies AttemptOutcome;\n }\n if (Exit.isFailure(establishment.exit)) {\n const isUnexpectedDefect =\n !Cause.hasInterruptsOnly(establishment.exit.cause) &&\n !establishment.exit.cause.reasons.some(Cause.isFailReason);\n const outcome = failureFromExit(target, establishment.exit, false, false);\n if (isUnexpectedDefect) {\n const defect = establishment.exit.cause.reasons.find(Cause.isDieReason)?.defect;\n yield* Effect.logError(\"Connection attempt failed with an unexpected defect.\").pipe(\n Effect.annotateLogs({\n \"environment.id\": target.environmentId,\n \"environment.label\": target.label,\n \"cause.reason_count\": establishment.exit.cause.reasons.length,\n ...safeErrorLogAttributes(defect),\n }),\n );\n }\n return outcome;\n }\n\n const active = establishment.exit.value;\n const currentIntent = yield* Ref.get(intent);\n if (!currentIntent.desired || currentIntent.network === \"offline\") {\n return {\n _tag: \"Interrupted\",\n established: false,\n stable: false,\n resetRetry: false,\n } satisfies AttemptOutcome;\n }\n\n const connectedAt = yield* Clock.currentTimeMillis;\n yield* SubscriptionRef.set(prepared, Option.some(active.lease.prepared));\n yield* SubscriptionRef.set(session, Option.some(active.lease.session));\n yield* setState({\n desired: true,\n network: currentIntent.network,\n phase: \"connected\",\n stage: null,\n attempt,\n generation,\n lastFailure: null,\n retryAt: null,\n });\n\n const connectedExit = yield* Effect.raceFirst(\n active.lease.session.closed.pipe(\n Effect.mapError(\n (error): TracedAttemptFailure => ({\n error,\n attemptSpan: active.attemptSpan,\n }),\n ),\n ),\n monitorConnectedLease(active.lease).pipe(\n Effect.mapError(\n (error): TracedAttemptFailure => ({\n error,\n attemptSpan: active.attemptSpan,\n }),\n ),\n ),\n ).pipe(exitUnlessInterrupted);\n const connectedForMs = (yield* Clock.currentTimeMillis) - connectedAt;\n if (Exit.isSuccess(connectedExit)) {\n return {\n _tag: \"Interrupted\",\n established: true,\n stable: connectedForMs >= BACKOFF_RESET_AFTER_MS,\n resetRetry: connectedExit.value,\n } satisfies AttemptOutcome;\n }\n return failureFromExit(target, connectedExit, true, connectedForMs >= BACKOFF_RESET_AFTER_MS);\n }, Effect.ensuring(clearLease));", + "checksum": "8c24ef212e1baf658eabc67c2a00996ebc7dae1354bb2d441368ff58e4b90f15" + }, + "reconnect-supervisor-generation-loop": { + "id": "reconnect-supervisor-generation-loop", + "path": "packages/client-runtime/src/connection/supervisor.ts", + "start": 643, + "end": 755, + "language": "typescript", + "label": "Environment supervisor generation, offline, retry, and backoff loop", + "code": " const run = Effect.fnUntraced(function* () {\n let failureCount = 0;\n let generation = 0;\n let latestFailure: ConnectionAttemptError | null = null;\n let pendingRetry = Option.none();\n const resetRetryLadder = () => {\n failureCount = 0;\n pendingRetry = Option.none();\n };\n\n for (;;) {\n if (yield* Ref.getAndSet(resetRetryState, false)) {\n failureCount = 0;\n latestFailure = null;\n pendingRetry = Option.none();\n }\n const currentIntent = yield* Ref.get(intent);\n if (!currentIntent.desired) {\n resetRetryLadder();\n latestFailure = null;\n yield* clearLease;\n yield* setState(availableState(currentIntent, generation));\n yield* waitForSignal;\n continue;\n }\n if (currentIntent.network === \"offline\") {\n yield* clearLease;\n yield* setState(offlineState(currentIntent, generation, failureCount + 1, latestFailure));\n const applicationActivated = yield* waitForSignal;\n if (applicationActivated) {\n resetRetryLadder();\n }\n continue;\n }\n\n const attempt = failureCount + 1;\n const nextGeneration = generation + 1;\n const outcome: AttemptOutcome = yield* Effect.scoped(\n runAttempt(attempt, nextGeneration, latestFailure, pendingRetry),\n );\n // Consumed on every iteration so a stale marker can never leak into a\n // later, unrelated failure.\n const failedWakeProbe = yield* Ref.getAndSet(wakeProbeFailed, false);\n if (outcome.established) {\n generation = nextGeneration;\n if (outcome.stable) {\n resetRetryLadder();\n latestFailure = null;\n }\n }\n if (outcome._tag === \"Interrupted\") {\n if (outcome.resetRetry) {\n resetRetryLadder();\n }\n continue;\n }\n\n const attemptSpan: Option.Option = outcome.failure.attemptSpan;\n const error: ConnectionAttemptError = outcome.failure.error;\n latestFailure = error;\n if (error._tag === \"ConnectionBlockedError\") {\n const blockedIntent = yield* Ref.get(intent);\n yield* setState({\n desired: blockedIntent.desired,\n network: blockedIntent.network,\n phase: \"blocked\",\n stage: null,\n attempt,\n generation,\n lastFailure: error,\n retryAt: null,\n });\n const applicationActivated = yield* waitForSignal;\n if (applicationActivated) {\n resetRetryLadder();\n }\n continue;\n }\n\n if (failedWakeProbe) {\n // The wake probe found a dead transport while the user is returning to\n // the app, so reconnect immediately instead of sleeping the first\n // backoff rung. Only this first attempt skips the ladder; if it fails\n // too, normal backoff resumes.\n resetRetryLadder();\n yield* setState(connectingState(yield* Ref.get(intent), generation, 1, error));\n continue;\n }\n\n failureCount += 1;\n const delayMs = retryDelayMs(failureCount - 1);\n pendingRetry = Option.map(attemptSpan, (previousAttempt) => ({\n previousAttempt,\n failureCount,\n delayMs,\n reason: error.reason,\n }));\n const failedIntent = yield* Ref.get(intent);\n yield* setState({\n desired: failedIntent.desired,\n network: failedIntent.network,\n phase: \"backoff\",\n stage: null,\n attempt,\n generation,\n lastFailure: error,\n retryAt: (yield* Clock.currentTimeMillis) + delayMs,\n });\n const applicationActivated = yield* waitForRetrySignal(delayMs);\n if (applicationActivated) {\n resetRetryLadder();\n }\n }", + "checksum": "c05d5d84a1e4a46eb365fbb096528c45b5defa3f110b2d0e7c7a56f19d0e21e5" + }, + "reconnect-shell-authoritative-refresh": { + "id": "reconnect-shell-authoritative-refresh", + "path": "packages/client-runtime/src/state/shell.ts", + "start": 138, + "end": 254, + "language": "typescript", + "label": "Shell cache, authoritative refresh, cursor, and synchronization boundary", + "code": " const applyItem = Effect.fn(\"EnvironmentShellState.applyItem\")(function* (\n item: OrchestrationShellStreamItem,\n ) {\n if (item.kind === \"synchronized\") {\n yield* Ref.set(awaitingCompletion, false);\n yield* SubscriptionRef.update(state, (current) =>\n Option.isSome(current.snapshot)\n ? { ...current, status: \"live\" as const, error: Option.none() }\n : current,\n );\n return;\n }\n\n const current = yield* SubscriptionRef.get(state);\n const nextSnapshot =\n item.kind === \"snapshot\"\n ? item.snapshot\n : Option.match(current.snapshot, {\n onNone: () => null,\n onSome: (snapshot) =>\n item.sequence > snapshot.snapshotSequence\n ? applyShellStreamEvent(snapshot, item)\n : snapshot,\n });\n if (nextSnapshot === null) {\n return;\n }\n\n const waiting = yield* Ref.get(awaitingCompletion);\n yield* SubscriptionRef.set(state, {\n snapshot: Option.some(nextSnapshot),\n status: waiting ? \"synchronizing\" : \"live\",\n error: Option.none(),\n });\n if (item.kind === \"snapshot\") {\n const session = yield* Ref.get(activeSubscriptionSession);\n if (session !== null) {\n yield* Ref.set(lastAuthoritativeSession, session);\n }\n }\n yield* Queue.offer(persistence, nextSnapshot);\n });\n\n const foregroundResubscriptions = Option.match(wakeups, {\n onNone: () => Stream.never,\n onSome: (service) =>\n service.changes.pipe(Stream.filter(ConnectionWakeups.shouldResubscribeAfterWakeup)),\n });\n\n yield* setSynchronizing;\n yield* Effect.forkScoped(\n subscribeDynamic(\n ORCHESTRATION_WS_METHODS.subscribeShell,\n Effect.fn(\"EnvironmentShellState.makeSubscribeInput\")(function* (session) {\n yield* Ref.set(activeSubscriptionSession, session);\n const supportsCompletionMarker = yield* session.initialConfig.pipe(\n Effect.map((config) => config.shellResumeCompletionMarker === true),\n Effect.orElseSucceed(() => false),\n );\n yield* Ref.set(awaitingCompletion, supportsCompletionMarker);\n yield* setSynchronizing;\n\n // Foreground resubscriptions on the same live session can resume from\n // the in-memory cursor. A new session reloads the authoritative HTTP\n // snapshot so a valid cursor cannot preserve incomplete cached data.\n const hasAuthoritativeSnapshot = (yield* Ref.get(lastAuthoritativeSession)) === session;\n let canResume = hasAuthoritativeSnapshot;\n let current = yield* SubscriptionRef.get(state);\n if (!hasAuthoritativeSnapshot || Option.isNone(current.snapshot)) {\n const prepared = yield* SubscriptionRef.get(supervisor.prepared).pipe(\n Effect.flatMap(\n Option.match({\n onSome: Effect.succeed,\n onNone: () =>\n SubscriptionRef.changes(supervisor.prepared).pipe(\n Stream.filter(Option.isSome),\n Stream.map((value) => value.value),\n Stream.runHead,\n Effect.map(Option.getOrThrow),\n ),\n }),\n ),\n );\n const httpSnapshot = yield* snapshotLoader.load(prepared);\n if (Option.isSome(httpSnapshot)) {\n yield* applyItem({ kind: \"snapshot\", snapshot: httpSnapshot.value });\n canResume = true;\n current = yield* SubscriptionRef.get(state);\n }\n }\n\n // If the authoritative refresh failed, omit the cached cursor so the\n // socket fallback sends a complete snapshot for this new session.\n if (!canResume || Option.isNone(current.snapshot)) {\n return supportsCompletionMarker ? { requestCompletionMarker: true as const } : {};\n }\n if (!supportsCompletionMarker) {\n // Without a completion marker there is no synchronized signal for a\n // resumed subscription, so report live immediately, like threads.\n yield* SubscriptionRef.update(state, (value) => ({\n ...value,\n status: \"live\" as const,\n error: Option.none(),\n }));\n }\n return {\n afterSequence: current.snapshot.value.snapshotSequence,\n ...(supportsCompletionMarker ? { requestCompletionMarker: true as const } : {}),\n };\n }),\n {\n onExpectedFailure: (cause) => setStreamError(Cause.squash(cause)),\n retryExpectedFailureAfter: \"250 millis\",\n resubscribe: foregroundResubscriptions,\n },\n ).pipe(Stream.runForEach(applyItem)),\n );", + "checksum": "1d9311e98f9edc09e36d4c35e425a45c477d9c51739b382efed42b285d41f19d" + }, + "reconnect-thread-snapshot-epoch": { + "id": "reconnect-thread-snapshot-epoch", + "path": "packages/client-runtime/src/state/threads.ts", + "start": 212, + "end": 338, + "language": "typescript", + "label": "Thread snapshot replacement and stale history epoch guard", + "code": " const setSynchronizing = SubscriptionRef.update(state, (current) =>\n current.status === \"deleted\"\n ? current\n : {\n ...current,\n status: \"synchronizing\" as const,\n error: Option.none(),\n },\n );\n const setReady = SubscriptionRef.update(state, (current) =>\n current.status === \"live\" || current.status === \"deleted\"\n ? current\n : {\n ...current,\n status: \"synchronizing\" as const,\n error: Option.none(),\n },\n );\n const setDisconnected = Effect.gen(function* () {\n yield* Ref.set(awaitingCompletion, false);\n // The capability belongs to the session that advertised it. During a\n // reconnect, a new prepared connection can exist before the new session's\n // config arrives; leaving the old value would let loadOlderTurns send\n // window parameters to a server that may not accept them (review\n // finding). makeSubscribeInput re-sets it from the next session's config.\n yield* Ref.set(paginationSupported, false);\n yield* SubscriptionRef.update(state, (current) => ({\n ...current,\n status: current.status === \"deleted\" ? current.status : statusWithoutLiveData(current.data),\n }));\n });\n const setStreamError = (cause: Cause.Cause) =>\n Ref.set(awaitingCompletion, false).pipe(\n Effect.andThen(\n SubscriptionRef.update(state, (current) => ({\n ...current,\n status:\n current.status === \"deleted\" ? current.status : statusWithoutLiveData(current.data),\n error: Option.some(formatThreadError(cause)),\n })),\n ),\n );\n\n const setThread = Effect.fn(\"EnvironmentThreadState.setThread\")(function* (\n thread: OrchestrationThread,\n // \"keep\" preserves the current page state (live events touch only loaded\n // recent turns); a snapshot or merged page passes its own page state.\n page: Option.Option | \"keep\",\n ) {\n const waiting = yield* Ref.get(awaitingCompletion);\n yield* SubscriptionRef.update(state, (current) => ({\n data: Option.some(thread),\n status: waiting ? (\"synchronizing\" as const) : (\"live\" as const),\n error: Option.none(),\n page: page === \"keep\" ? current.page : page,\n }));\n // Active threads can update many times per second and retain large tool\n // payloads. The server remains the source of truth while a turn is active;\n // persist once it settles so cache encoding stays off the streaming path.\n if (shouldPersistThread(thread)) {\n const snapshotSequence = yield* SubscriptionRef.get(lastSequence);\n const currentPage = yield* SubscriptionRef.get(state).pipe(Effect.map((value) => value.page));\n yield* Queue.offer(persistence, {\n snapshotSequence,\n thread,\n // Persist the window boundary with the window's content so a cache\n // restore can keep paging from where the loaded history ends.\n ...Option.match(currentPage, {\n onNone: () => ({}),\n onSome: (value) =>\n ({\n page: {\n beforeCursor: value.beforeCursor,\n hasMore: value.hasMore,\n snapshotSequence,\n },\n }) as const,\n }),\n });\n }\n });\n\n const setDeleted = Effect.fn(\"EnvironmentThreadState.setDeleted\")(function* () {\n yield* Ref.set(awaitingCompletion, false);\n yield* Ref.update(historyEpoch, (epoch) => epoch + 1);\n yield* SubscriptionRef.set(state, {\n data: Option.none(),\n status: \"deleted\",\n error: Option.none(),\n page: Option.none(),\n });\n yield* cache.removeThread(environmentId, threadId).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\"Could not remove the cached thread.\").pipe(\n Effect.annotateLogs({\n environmentId,\n threadId,\n error: error.message,\n }),\n ),\n ),\n );\n });\n\n // Body of applyItem, running under applyLock.\n const applyItemLocked = Effect.fn(\"EnvironmentThreadState.applyItemLocked\")(function* (\n item: OrchestrationThreadStreamItem,\n ) {\n if (item.kind === \"synchronized\") {\n yield* Ref.set(awaitingCompletion, false);\n yield* SubscriptionRef.update(state, (current) =>\n Option.isSome(current.data) && current.status !== \"deleted\"\n ? { ...current, status: \"live\" as const, error: Option.none() }\n : current,\n );\n return;\n }\n\n if (item.kind === \"snapshot\") {\n // A fresh snapshot replaces all loaded history, including older\n // pages: a turn reverted while disconnected would otherwise survive\n // in the preserved history with no event left to remove it. The\n // epoch bump discards any older-page fetch racing this snapshot.\n yield* Ref.update(historyEpoch, (epoch) => epoch + 1);\n yield* SubscriptionRef.set(lastSequence, item.snapshot.snapshotSequence);\n yield* setThread(item.snapshot.thread, pageStateFromSnapshot(item.snapshot.page));\n return;", + "checksum": "a0068277d9fe46a387efaa9dbd9414d8eb43bb6f0d99cc1a8e353269d62d4838" + }, + "reconnect-mobile-background-demand": { + "id": "reconnect-mobile-background-demand", + "path": "apps/mobile/src/connection/background-activity.ts", + "start": 44, + "end": 115, + "language": "typescript", + "label": "Mobile background activity reports and retained environment demand", + "code": "export const mobileBackgroundActivityReporterLayer = Layer.effectDiscard(\n Effect.gen(function* () {\n const registry = yield* EnvironmentRegistry;\n const storage = yield* MobileStorage.MobileStorage;\n const clientId = yield* storage.loadOrCreateAgentAwarenessDeviceId.pipe(\n Effect.map((deviceId) => `mobile-${deviceId}`),\n Effect.orElseSucceed(() => \"ephemeral-mobile-client\"),\n );\n const reportRequests = yield* Queue.sliding(1);\n const requestReport = () => Queue.offerUnsafe(reportRequests, undefined);\n let appState = AppState.currentState;\n\n const report = Effect.gen(function* () {\n const observedAtMs = yield* Clock.currentTimeMillis;\n const active = appState === \"active\";\n const entries = yield* SubscriptionRef.get(registry.entries);\n yield* Effect.forEach(\n entries.keys(),\n (environmentId) =>\n registry\n .run(\n environmentId,\n request(WS_METHODS.serverReportClientActivity, {\n environmentId: environmentId as EnvironmentId,\n clientId,\n clientKind: \"mobile\",\n visible: active,\n focused: active,\n recentlyInteracted: active,\n appState: normalizeAppState(appState),\n scopes: [\n ...BASELINE_SCOPES,\n ...retainedMobileBackgroundScopes(environmentId as EnvironmentId),\n ],\n ttlMs: LEASE_TTL_MS,\n observedAt: DateTime.makeUnsafe(observedAtMs),\n }),\n )\n .pipe(Effect.ignore),\n { concurrency: \"unbounded\", discard: true },\n );\n }).pipe(Effect.withSpan(\"mobile.backgroundActivity.report\"));\n\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n const removeScopeListener = onRetainedMobileBackgroundScopesChange(requestReport);\n const subscription = AppState.addEventListener(\"change\", (nextState) => {\n appState = nextState;\n requestReport();\n });\n return { removeScopeListener, subscription };\n }),\n ({ removeScopeListener, subscription }) =>\n Effect.sync(() => {\n removeScopeListener();\n subscription.remove();\n }),\n );\n yield* SubscriptionRef.changes(registry.entries).pipe(\n Stream.runForEach(() => Effect.sync(requestReport)),\n Effect.forkScoped,\n );\n yield* Stream.fromQueue(reportRequests).pipe(\n Stream.debounce(\"250 millis\"),\n Stream.runForEach(() => report),\n Effect.forkScoped,\n );\n yield* Effect.sync(requestReport).pipe(\n Effect.repeat(Schedule.spaced(`${REPORT_INTERVAL_MS} millis`)),\n Effect.forkScoped,\n );\n }),", + "checksum": "1ee6a99a5ee47b441952a1ce0fcd1ed9ae24e67ae35ce7d3af3ece7bc5e91b20" + }, + "reconnect-mobile-background-scopes": { + "id": "reconnect-mobile-background-scopes", + "path": "apps/mobile/src/connection/background-activity-scopes.ts", + "start": 24, + "end": 84, + "language": "typescript", + "label": "Reference-counted environment background scopes", + "code": "function stableScopeKey(environmentId: EnvironmentId, scope: BackgroundScope): string {\n switch (scope.type) {\n case \"server-config\":\n case \"diagnostics\":\n return JSON.stringify([environmentId, scope.type]);\n case \"provider-status\":\n return JSON.stringify([environmentId, scope.type, scope.instanceId ?? null]);\n case \"vcs-status\":\n case \"git-refs\":\n return JSON.stringify([environmentId, scope.type, scope.cwd]);\n case \"thread\":\n return JSON.stringify([environmentId, scope.type, scope.threadId]);\n }\n}\n\nfunction scopeForSubscription(\n observation: EnvironmentRpcSubscriptionObservation,\n): BackgroundScope | null {\n if (observation.method === WS_METHODS.subscribeResourceTelemetry) {\n return { type: \"diagnostics\" };\n }\n if (observation.method !== WS_METHODS.subscribeVcsStatus) {\n return null;\n }\n const input = observation.input as { readonly cwd?: unknown };\n return typeof input.cwd === \"string\" ? { type: \"vcs-status\", cwd: input.cwd } : null;\n}\n\nexport function retainedMobileBackgroundScopes(\n environmentId: EnvironmentId,\n): ReadonlyArray {\n return Array.from(retainedScopes.values(), (entry) =>\n entry.environmentId === environmentId ? entry.scope : null,\n ).filter((scope): scope is BackgroundScope => scope !== null);\n}\n\nexport function observeMobileBackgroundActivitySubscription(\n observation: EnvironmentRpcSubscriptionObservation,\n): Effect.Effect> {\n const scope = scopeForSubscription(observation);\n if (scope === null) return Effect.succeed(Effect.void);\n return Effect.sync(() => {\n const environmentId = observation.environmentId as EnvironmentId;\n const key = stableScopeKey(environmentId, scope);\n const current = retainedScopes.get(key);\n if (current) {\n current.refCount += 1;\n } else {\n retainedScopes.set(key, { environmentId, scope, refCount: 1 });\n notify();\n }\n return Effect.sync(() => {\n const retained = retainedScopes.get(key);\n if (!retained) return;\n retained.refCount -= 1;\n if (retained.refCount <= 0) {\n retainedScopes.delete(key);\n notify();\n }\n });\n });", + "checksum": "068d56fe85a7b15f425609c38d6f76e6cbb5077ff55cbafe0cba73903a029f7e" + }, + "awareness-relay-signal-filter": { + "id": "awareness-relay-signal-filter", + "path": "apps/server/src/relay/AgentAwarenessRelay.ts", + "start": 69, + "end": 133, + "language": "typescript", + "label": "Awareness event filtering and projected-state sanitization", + "code": "export function shouldPublishAgentAwarenessEvent(event: OrchestrationEvent): boolean {\n switch (event.type) {\n case \"thread.message-sent\":\n case \"thread.turn-start-requested\":\n // These events express intent to start work, but the shell still contains\n // the previous turn's terminal state until the provider acknowledges the\n // new turn. Publishing that snapshot can queue a fresh \"Done\" alert just\n // before the real running state arrives. Provider lifecycle events publish\n // the authoritative starting/running state instead.\n return false;\n case \"thread.proposed-plan-upserted\":\n case \"thread.runtime-mode-set\":\n case \"thread.interaction-mode-set\":\n return false;\n case \"thread.activity-appended\":\n return (\n event.payload.activity.kind === \"approval.requested\" ||\n event.payload.activity.kind === \"approval.resolved\" ||\n event.payload.activity.kind === \"provider.approval.respond.failed\" ||\n event.payload.activity.kind === \"user-input.requested\" ||\n event.payload.activity.kind === \"user-input.resolved\" ||\n event.payload.activity.kind === \"runtime.error\"\n );\n default:\n return true;\n }\n}\n\nexport function agentAwarenessPublishIdentity(state: RelayAgentActivityState | null): string {\n if (state === null) {\n return \"null\";\n }\n const { updatedAt: _updatedAt, ...meaningfulState } = state;\n return JSON.stringify(meaningfulState);\n}\n\nexport function isAgentActivityPublishingEnabled(value: string | null): boolean {\n return isAgentActivityPublishingEnabledValue(value);\n}\n\nexport function resolveAgentActivityPublishingStartupState(input: {\n readonly relayConfigured: boolean;\n readonly publishEnabled: boolean;\n}): \"waiting-for-link\" | \"disabled\" | \"enabled\" {\n if (!input.relayConfigured) {\n return \"waiting-for-link\";\n }\n return input.publishEnabled ? \"enabled\" : \"disabled\";\n}\n\nconst RELAY_AGENT_ACTIVITY_DETAIL_MAX_LENGTH = 160;\nconst REDACTED_RELAY_AGENT_FAILURE_DETAIL = \"The agent run failed.\";\n\nexport function sanitizeRelayAgentActivityState(\n state: RelayAgentActivityState | null,\n): RelayAgentActivityState | null {\n if (state === null) {\n return null;\n }\n const { detail: _detail, ...rest } = state;\n const detail = (state.phase === \"failed\" ? REDACTED_RELAY_AGENT_FAILURE_DETAIL : state.detail)\n ?.trim()\n .slice(0, RELAY_AGENT_ACTIVITY_DETAIL_MAX_LENGTH)\n .trim();\n return detail ? { ...rest, detail } : rest;", + "checksum": "cf128f94bb354ee125fea15b45caa64e3fd9014530925e9164bc6530d11d9818" + }, + "awareness-relay-projected-publish": { + "id": "awareness-relay-projected-publish", + "path": "apps/server/src/relay/AgentAwarenessRelay.ts", + "start": 345, + "end": 426, + "language": "typescript", + "label": "Signed awareness publish and unchanged-state suppression", + "code": " const publishThreadUnsafe = Effect.fn(\"publishThreadUnsafe\")(function* (threadId: ThreadId) {\n const publishAgentActivity = yield* readPublishAgentActivityEnabled.pipe(\n Effect.orElseSucceed(() => false),\n );\n if (!publishAgentActivity) {\n yield* Effect.logDebug(\"agent activity publish skipped; publication disabled\", {\n threadId,\n });\n return;\n }\n const relayConfig = yield* readRelayConfig.pipe(Effect.orElseSucceed(() => null));\n if (!relayConfig) {\n yield* Effect.logDebug(\"agent activity publish skipped; relay link credentials unavailable\", {\n threadId,\n });\n return;\n }\n const relayClient = yield* makeRelayClient(relayConfig);\n const environmentId = yield* serverEnvironment.getEnvironmentId;\n\n const publishState = (input: {\n readonly projectId: string | null;\n readonly state: RelayAgentActivityState | null;\n readonly reason: string;\n }) =>\n Effect.gen(function* () {\n const proof = yield* makePublishProof({\n privateKey: cloudLinkKeyPair.privateKey,\n relayIssuer: relayConfig.issuer,\n environmentId,\n threadId,\n state: input.state,\n jti: yield* crypto.randomUUIDv4,\n });\n\n yield* Effect.logInfo(\"publishing agent activity for thread\", {\n environmentId,\n threadId,\n projectId: input.projectId,\n statePhase: input.state?.phase ?? null,\n hasState: input.state !== null,\n reason: input.reason,\n });\n\n const response = yield* relayClient.server.publishAgentActivity({\n params: {\n environmentId,\n threadId,\n },\n payload: {\n state: input.state,\n proof,\n },\n });\n\n yield* Effect.logInfo(\"agent activity publish completed\", {\n environmentId,\n threadId,\n ok: response.ok,\n deliveries: deliveryStats(response.deliveries),\n });\n });\n\n const thread = yield* snapshotQuery.getThreadShellById(threadId);\n const project = Option.isSome(thread)\n ? yield* snapshotQuery.getProjectShellById(thread.value.projectId)\n : Option.none();\n const snapshot = resolveAgentAwarenessRelayPublishSnapshot({\n environmentId,\n threadId,\n thread,\n project,\n });\n const publishIdentity = agentAwarenessPublishIdentity(snapshot.state);\n const publishedStateByThread = yield* Ref.get(publishedStateByThreadRef);\n if (publishedStateByThread.get(threadId) === publishIdentity) {\n // The projection is back at (or never left) the last published state, so\n // any pending deferred confirmation is moot. Leaving the deadline in\n // place would let a much later transient null find it already expired\n // and publish a tombstone immediately, skipping the deferral window.\n publishConfirmDeadlines.delete(threadId);\n yield* Effect.logDebug(\"agent activity publish skipped; projected state unchanged\", {", + "checksum": "6d030e7bb0a96b730ec457746e28f39d9a868e1065b4e67bc59a0e5329c576f5" + }, + "awareness-apns-delivery-policy": { + "id": "awareness-apns-delivery-policy", + "path": "infra/relay/src/agentActivity/ApnsDeliveries.ts", + "start": 143, + "end": 326, + "language": "typescript", + "label": "APNs alert gating and Live Activity delivery cadence", + "code": "function aggregateNeedsAttention(aggregate: RelayAgentActivityAggregateState): boolean {\n return aggregate.activities.some(\n (row) => row.phase === \"waiting_for_approval\" || row.phase === \"waiting_for_input\",\n );\n}\n\nfunction isAttentionPhase(phase: string): boolean {\n return phase === \"waiting_for_approval\" || phase === \"waiting_for_input\";\n}\n\n// Honors the same per-event notification switches the push channel uses; a\n// missing/corrupt preferences blob only disables nothing (matching how the\n// liveActivitiesEnabled check treats it), since every registration writes one.\nfunction alertAllowedForPhase(\n preferences: RelayAgentAwarenessPreferences | null,\n phase: string,\n): boolean {\n if (preferences === null) {\n return true;\n }\n switch (phase) {\n case \"waiting_for_approval\":\n return preferences.notifyOnApproval;\n case \"waiting_for_input\":\n return preferences.notifyOnInput;\n case \"completed\":\n return preferences.notifyOnCompletion;\n case \"failed\":\n return preferences.notifyOnFailure;\n default:\n return false;\n }\n}\n\n// Alert copy for an update whose aggregate contains threads that were NOT in an\n// attention phase in the previously delivered aggregate. A null previous\n// aggregate means there is no known baseline (fresh registration, replay after\n// data loss) — alerting there would buzz on reconnect, not on a transition.\nexport function alertForAttentionTransition(input: {\n readonly previousAggregate: RelayAgentActivityAggregateState | null;\n readonly nextAggregate: RelayAgentActivityAggregateState;\n readonly preferences: RelayAgentAwarenessPreferences | null;\n}): ApnsLiveActivityAlert | null {\n if (input.previousAggregate === null) {\n return null;\n }\n const previouslyAttention = new Set(\n input.previousAggregate.activities\n .filter((row) => isAttentionPhase(row.phase))\n .map((row) => row.threadId),\n );\n const newlyAttention = input.nextAggregate.activities.filter(\n (row) =>\n isAttentionPhase(row.phase) &&\n !previouslyAttention.has(row.threadId) &&\n alertAllowedForPhase(input.preferences, row.phase),\n );\n const first = newlyAttention[0];\n if (!first) {\n return null;\n }\n if (newlyAttention.length === 1) {\n return { title: first.threadTitle, body: `${first.status}: ${first.projectTitle}` };\n }\n return {\n title: `${newlyAttention.length} agents need attention`,\n body: newlyAttention.map((row) => row.threadTitle).join(\", \"),\n };\n}\n\n// Alert copy for an update whose aggregate contains threads that finished\n// (Done/Failed) since the previously delivered aggregate — the mid-flight\n// completion buzz while other agents keep the activity alive. Requires the\n// thread to have been present and non-terminal before, so a baseline-less\n// replay or a row that merely fell off the display cap never rings.\nfunction newlyTerminalRows(\n previousAggregate: RelayAgentActivityAggregateState | null,\n nextAggregate: RelayAgentActivityAggregateState,\n): ReadonlyArray {\n if (previousAggregate === null) {\n return [];\n }\n const previousPhases = new Map(\n previousAggregate.activities.map((row) => [row.threadId, row.phase]),\n );\n return nextAggregate.activities.filter((row) => {\n if (row.phase !== \"completed\" && row.phase !== \"failed\") {\n return false;\n }\n const previousPhase = previousPhases.get(row.threadId);\n return (\n previousPhase !== undefined && previousPhase !== \"completed\" && previousPhase !== \"failed\"\n );\n });\n}\n\nfunction isFreshTerminalRow(\n row: RelayAgentActivityAggregateState[\"activities\"][number],\n nowMs: number,\n): boolean {\n const updatedAtMs = Option.match(DateTime.make(row.updatedAt), {\n onNone: () => null,\n onSome: (dt) => dt.epochMilliseconds,\n });\n return updatedAtMs !== null && nowMs - updatedAtMs <= TERMINAL_NOTIFICATION_FRESHNESS_MS;\n}\n\nexport function alertForNewlyTerminal(input: {\n readonly previousAggregate: RelayAgentActivityAggregateState | null;\n readonly nextAggregate: RelayAgentActivityAggregateState;\n readonly preferences: RelayAgentAwarenessPreferences | null;\n readonly nowMs: number;\n}): ApnsLiveActivityAlert | null {\n const newlyTerminal = newlyTerminalRows(input.previousAggregate, input.nextAggregate).filter(\n (row) =>\n alertAllowedForPhase(input.preferences, row.phase) &&\n // Replays of old aggregates (server restarts, redeliveries) repaint\n // state without ringing; only fresh completions buzz.\n isFreshTerminalRow(row, input.nowMs),\n );\n const first = newlyTerminal[0];\n if (!first) {\n return null;\n }\n if (newlyTerminal.length === 1) {\n return { title: first.threadTitle, body: `${first.status}: ${first.projectTitle}` };\n }\n return {\n title: `${newlyTerminal.length} agents finished`,\n body: newlyTerminal.map((row) => row.threadTitle).join(\", \"),\n };\n}\n\n// Alert copy for an end event carrying a terminal (Done/Failed) aggregate.\nexport function alertForTerminalAggregate(input: {\n readonly aggregate: RelayAgentActivityAggregateState | null;\n readonly preferences: RelayAgentAwarenessPreferences | null;\n}): ApnsLiveActivityAlert | null {\n const row = input.aggregate?.activities[0];\n if (!row || (row.phase !== \"completed\" && row.phase !== \"failed\")) {\n return null;\n }\n if (!alertAllowedForPhase(input.preferences, row.phase)) {\n return null;\n }\n return { title: row.threadTitle, body: `${row.status}: ${row.projectTitle}` };\n}\n\nfunction shouldUpdateLiveActivity(input: {\n readonly previousAggregate: RelayAgentActivityAggregateState | null;\n readonly nextAggregate: RelayAgentActivityAggregateState;\n readonly lastDeliveryAt: string | null;\n readonly nowMs: number;\n}): boolean {\n if (!input.previousAggregate) {\n return true;\n }\n if (JSON.stringify(input.previousAggregate) === JSON.stringify(input.nextAggregate)) {\n return false;\n }\n if (input.previousAggregate.activeCount !== input.nextAggregate.activeCount) {\n return true;\n }\n if (aggregateNeedsAttention(input.nextAggregate)) {\n return true;\n }\n // A thread finishing must never be throttled away: when a completion and a\n // new start land in the same window, activeCount is unchanged and the Done\n // transition (and its alert) would otherwise be suppressed.\n if (newlyTerminalRows(input.previousAggregate, input.nextAggregate).length > 0) {\n return true;\n }\n const lastDeliveryAtMs =\n input.lastDeliveryAt === null\n ? null\n : Option.match(DateTime.make(input.lastDeliveryAt), {\n onNone: () => Number.NaN,\n onSome: (dt) => dt.epochMilliseconds,\n });\n return (\n lastDeliveryAtMs === null ||\n Number.isNaN(lastDeliveryAtMs) ||\n input.nowMs - lastDeliveryAtMs >= MIN_LIVE_ACTIVITY_UPDATE_INTERVAL_MS\n );", + "checksum": "50723205408ac50c442297f150778cbc2e74d222107af1646291a50932203a8e" + }, + "awareness-mobile-registration-gate": { + "id": "awareness-mobile-registration-gate", + "path": "apps/mobile/src/features/agent-awareness/remoteRegistration.ts", + "start": 69, + "end": 90, + "language": "typescript", + "label": "Relay-accepted mobile registration and replay repair boundary", + "code": "const environmentConnections = new Map();\nconst activityPushTokenListeners = new WeakSet>();\n// Activity tokens the relay recently accepted, by acceptance time. The refresh\n// runs on sign-in, every app foreground, and every environment-connection\n// update, which arrive in bursts and spammed identical registrations. But the\n// registration is not a pure no-op: the relay replays the current aggregate to\n// this device on every accepted registration, and that replay is the\n// foreground reconciliation that repairs drifted or orphaned activities. So\n// dedupe only within a short window — bursts collapse to one request, while a\n// foreground after real time away still triggers a replay. Cleared on\n// sign-out/identity change alongside the device registration state.\nconst ACTIVITY_TOKEN_REREGISTER_INTERVAL_MS = 60_000;\nconst registeredActivityPushTokens = new Map();\nlet pushTokenSubscription: { remove: () => void } | null = null;\nlet appStateSubscription: { remove: () => void } | null = null;\n\n// Whether the relay has actually accepted this device's registration. The\n// notification/Live Activity settings toggles must reflect this rather than\n// only local iOS permission or saved preferences: if the registration request\n// never succeeded, the device cannot receive anything, so the switches must\n// not read as enabled.\nexport type AgentAwarenessRegistrationStatus = \"unknown\" | \"pending\" | \"registered\" | \"failed\";", + "checksum": "20d6bf8e2a049ae450c3958d6c8e90cdbcaff94bb0cc90602bed5aeee8b0b3a1" + }, + "awareness-notification-navigation": { + "id": "awareness-notification-navigation", + "path": "apps/mobile/src/features/agent-awareness/notificationPayload.ts", + "start": 37, + "end": 105, + "language": "typescript", + "label": "Notification payload normalization, deduplication, and navigation", + "code": "function encodeThreadDeepLink(input: {\n readonly environmentId: string;\n readonly threadId: string;\n}): string | null {\n if (input.environmentId.length === 0 || input.threadId.length === 0) {\n return null;\n }\n return `/threads/${encodeURIComponent(input.environmentId)}/${encodeURIComponent(input.threadId)}`;\n}\n\nfunction normalizeThreadDeepLink(value: string): string | null {\n if (\n value.trim() !== value ||\n value.startsWith(\"//\") ||\n value.includes(\"?\") ||\n value.includes(\"#\")\n ) {\n return null;\n }\n\n const parts = value.split(\"/\");\n if (parts.length !== 4 || parts[0] !== \"\" || parts[1] !== \"threads\") {\n return null;\n }\n\n try {\n return encodeThreadDeepLink({\n environmentId: decodeURIComponent(parts[2] ?? \"\"),\n threadId: decodeURIComponent(parts[3] ?? \"\"),\n });\n } catch {\n return null;\n }\n}\n\nexport function extractAgentNotificationDeepLink(response: unknown): string | null {\n const data = dataFromNotificationResponse(response);\n const deepLink = data?.deepLink;\n if (typeof deepLink === \"string\") {\n const normalizedDeepLink = normalizeThreadDeepLink(deepLink);\n if (normalizedDeepLink) {\n return normalizedDeepLink;\n }\n }\n\n const environmentId = data?.environmentId;\n const threadId = data?.threadId;\n if (typeof environmentId === \"string\" && typeof threadId === \"string\") {\n return encodeThreadDeepLink({ environmentId, threadId });\n }\n return null;\n}\n\nexport function routeAgentNotificationResponseOnce(input: {\n readonly handledResponseIds: Set;\n readonly response: unknown;\n readonly navigate: (deepLink: string) => void;\n}): void {\n const responseId = identifierFromNotificationResponse(input.response);\n if (responseId && input.handledResponseIds.has(responseId)) {\n return;\n }\n if (responseId) {\n input.handledResponseIds.add(responseId);\n }\n const deepLink = extractAgentNotificationDeepLink(input.response);\n if (deepLink) {\n input.navigate(deepLink);\n }", + "checksum": "2fad0a887c90a1d5575437758a8f2935fae5c4d77aba4e728221391123165783" + }, + "reconnect-capability-descriptor": { + "id": "reconnect-capability-descriptor", + "path": "packages/contracts/src/environment.ts", + "start": 31, + "end": 92, + "language": "typescript", + "label": "Environment version and optional capability descriptor", + "code": "/** How a server can replace itself with another version when asked over RPC.\n New servers only advertise the stable launcher-backed \"boot-service\" path;\n \"respawn\" remains decodable for compatibility with older servers. */\nexport const ServerSelfUpdateMethod = Schema.Literals([\"boot-service\", \"respawn\"]);\nexport type ServerSelfUpdateMethod = typeof ServerSelfUpdateMethod.Type;\n\n/** What update path a client should offer for a server: one of the RPC\n self-update methods above, or \"desktop-managed\" when the backend's\n version belongs to the T3 Code desktop app supervising it — updating the\n app on that machine is the only way to update the server. */\nexport const ServerSelfUpdateCapability = Schema.Literals([\n \"boot-service\",\n \"respawn\",\n \"desktop-managed\",\n]);\nexport type ServerSelfUpdateCapability = typeof ServerSelfUpdateCapability.Type;\n\nexport const ExecutionEnvironmentCapabilities = Schema.Struct({\n repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),\n connectionProbe: Schema.optionalKey(Schema.Boolean),\n /** Server exposes the pull-request list, detail, activity, diff, and mutation APIs. Absent on\n servers from before the pull-request workspace shipped, so clients must not probe them. */\n pullRequests: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.settle / thread.unsettle commands. Absent on\n pre-settlement servers, so clients treat missing as unsupported and\n never send the commands under version skew. */\n threadSettlement: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.snooze / thread.unsnooze commands. Same\n version-skew contract as threadSettlement. */\n threadSnooze: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.pin / thread.unpin commands. Same\n version-skew contract as threadSettlement. */\n threadPinning: Schema.optionalKey(Schema.Boolean),\n /** Server understands thread.pin.reorder (and orderKey on thread.pin).\n Same version-skew contract as threadSettlement. */\n threadPinReorder: Schema.optionalKey(Schema.Boolean),\n /** Server understands regenerateTitle on thread.meta.update. Absent on\n older servers, so clients hide the action instead of sending it. */\n threadTitleRegeneration: Schema.optionalKey(Schema.Boolean),\n /** The update path clients should offer for this server. Absent on\n servers that must be relaunched manually (dev checkouts, Windows\n foreground runs, pre-update servers). */\n serverSelfUpdate: Schema.optionalKey(ServerSelfUpdateCapability),\n /** Server can stream self-update progress before acknowledging the\n restart. Clients fall back to server.updateServer when absent. */\n serverSelfUpdateProgress: Schema.optionalKey(Schema.Boolean),\n /** Agent-activity publishes (push notifications and Live Activities)\n currently leave this environment: the publish opt-in is enabled and the\n relay link credentials exist. Clients skip seeding a Live Activity when\n this is false — no update would ever repaint it. Absent on older\n servers, which may still publish, so only an explicit false skips. */\n agentActivityPublishing: Schema.optionalKey(Schema.Boolean),\n});\nexport type ExecutionEnvironmentCapabilities = typeof ExecutionEnvironmentCapabilities.Type;\n\nexport const ExecutionEnvironmentDescriptor = Schema.Struct({\n environmentId: EnvironmentId,\n label: TrimmedNonEmptyString,\n platform: ExecutionEnvironmentPlatform,\n serverVersion: TrimmedNonEmptyString,\n capabilities: ExecutionEnvironmentCapabilities,\n});", + "checksum": "5dbb79216344a256d038ab70c0befe0773721b63fa7d60caef52901ed5fa7cca" + }, + "reconnect-version-skew-guidance": { + "id": "reconnect-version-skew-guidance", + "path": "apps/web/src/versionSkew.ts", + "start": 21, + "end": 130, + "language": "typescript", + "label": "Exact client-server version comparison and update guidance", + "code": "function normalizeVersion(version: string | null | undefined): string | null {\n const trimmed = version?.trim();\n return trimmed && trimmed.length > 0 ? trimmed : null;\n}\n\nexport function resolveVersionMismatch(\n serverVersion: string | null | undefined,\n): VersionMismatch | null {\n const normalizedClientVersion = normalizeVersion(APP_VERSION);\n const normalizedServerVersion = normalizeVersion(serverVersion);\n if (\n !normalizedClientVersion ||\n !normalizedServerVersion ||\n normalizedClientVersion === normalizedServerVersion\n ) {\n return null;\n }\n\n return {\n clientVersion: normalizedClientVersion,\n serverVersion: normalizedServerVersion,\n hint: \"Version mismatch. Try syncing the client and server to the same T3 Code version.\",\n };\n}\n\nexport function resolveServerConfigVersionMismatch(\n serverConfig: Pick | null | undefined,\n): VersionMismatch | null {\n return resolveVersionMismatch(serverConfig?.environment.serverVersion);\n}\n\n/** The update path the connected server offers, or null when it only\n supports a manual relaunch (older servers, dev checkouts, Windows). */\nexport function resolveServerSelfUpdateCapability(\n serverConfig: Pick | null | undefined,\n): ServerSelfUpdateCapability | null {\n return serverConfig?.environment.capabilities.serverSelfUpdate ?? null;\n}\n\n/** The command to hand users whose server cannot update itself. */\nexport function manualServerUpdateCommand(targetVersion: string): string {\n return `npx t3@${targetVersion}`;\n}\n\n/** One sentence telling the user how to resolve version skew for a server,\n matched to the update path it offers. */\nexport function serverUpdateGuidance(\n capability: ServerSelfUpdateCapability | null,\n serverLabel: string,\n): string {\n switch (capability) {\n case \"boot-service\":\n case \"respawn\":\n return `Update the ${serverLabel} so they stay in sync.`;\n case \"desktop-managed\":\n return `Update the desktop app that runs the ${serverLabel}.`;\n default:\n return `Relaunch the ${serverLabel} with the copied command to sync them.`;\n }\n}\n\nexport function buildVersionMismatchDismissalKey(\n environmentId: EnvironmentId,\n mismatch: Pick,\n): string {\n return `${environmentId}:${mismatch.clientVersion}:${mismatch.serverVersion}`;\n}\n\nfunction readVersionMismatchDismissals(): VersionMismatchDismissals {\n try {\n return (\n getLocalStorageItem(\n VERSION_MISMATCH_DISMISSALS_STORAGE_KEY,\n VersionMismatchDismissalsSchema,\n ) ?? { keys: [] }\n );\n } catch (error) {\n console.error(\"Could not read version-mismatch dismissals.\", error);\n return { keys: [] };\n }\n}\n\nfunction writeVersionMismatchDismissals(document: VersionMismatchDismissals): void {\n try {\n setLocalStorageItem(\n VERSION_MISMATCH_DISMISSALS_STORAGE_KEY,\n document,\n VersionMismatchDismissalsSchema,\n );\n } catch (error) {\n console.error(\"Could not persist version-mismatch dismissals.\", error);\n }\n}\n\nexport function isVersionMismatchDismissed(dismissalKey: string | null | undefined): boolean {\n if (!dismissalKey) {\n return false;\n }\n return readVersionMismatchDismissals().keys.includes(dismissalKey);\n}\n\nexport function dismissVersionMismatch(dismissalKey: string | null | undefined): void {\n if (!dismissalKey) {\n return;\n }\n const document = readVersionMismatchDismissals();\n if (document.keys.includes(dismissalKey)) {\n return;\n }\n writeVersionMismatchDismissals({", + "checksum": "493e23986ed26727ea268f4e5ebc7a939ca984654515b3fccfad44cc899386f0" + }, + "reconnect-exact-version-update": { + "id": "reconnect-exact-version-update", + "path": "apps/server/src/cloud/selfUpdate.ts", + "start": 30, + "end": 190, + "language": "typescript", + "label": "Exact-version staging, preflight, and launcher activation handoff", + "code": "export function resolveServerSelfUpdateCapability(input: {\n readonly desktopManaged: boolean;\n readonly launcherManaged: boolean;\n}): ServerSelfUpdateCapability | null {\n if (input.desktopManaged) return \"desktop-managed\" as const;\n return input.launcherManaged ? (\"boot-service\" as const) : null;\n}\n\nexport class ServerSelfUpdate extends Context.Service<\n ServerSelfUpdate,\n {\n readonly update: (\n input: ServerSelfUpdateInput,\n reportProgress?: (stage: ServerSelfUpdateProgressStage) => Effect.Effect,\n ) => Effect.Effect;\n }\n>()(\"t3/cloud/selfUpdate/ServerSelfUpdate\") {}\n\nexport const make = Effect.fn(\"cloud.server_self_update.make\")(function* () {\n const serverConfig = yield* ServerConfig.ServerConfig;\n const launcher = yield* ServiceLauncherClient.ServiceLauncherClient;\n const runner = yield* ProcessRunner.ProcessRunner;\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const execPath = yield* HostProcessExecutablePath;\n const inFlight = yield* Ref.make(false);\n\n const capability: ServerSelfUpdateCapability | null =\n serverConfig.mode === \"desktop\" ? \"desktop-managed\" : launcher.managed ? \"boot-service\" : null;\n const failWith = (reason: string, cause?: unknown) =>\n cause === undefined\n ? new ServerSelfUpdateError({ reason })\n : new ServerSelfUpdateError({ reason, cause });\n\n const update: ServerSelfUpdate[\"Service\"][\"update\"] = Effect.fn(\n \"cloud.server_self_update.update\",\n )(function* (input, reportProgress = () => Effect.void) {\n if (capability === \"desktop-managed\") {\n return yield* failWith(\n \"This server is managed by the T3 Code desktop app on its machine; update the desktop app to update it.\",\n );\n }\n if (capability === null) {\n return yield* failWith(\n \"Remote updates require the T3 Code background service. Run `t3 service install` on the server machine.\",\n );\n }\n\n const targetVersion = input.targetVersion.trim();\n if (!isExactServiceVersion(targetVersion)) {\n return yield* failWith(`'${targetVersion}' is not an exact t3 version.`);\n }\n if (yield* Ref.getAndSet(inFlight, true)) {\n return yield* failWith(\"A server update is already in progress.\");\n }\n\n return yield* Effect.gen(function* () {\n yield* reportProgress(\"downloading\");\n const paths = yield* ensurePinnedRuntimeInstalled({\n baseDir: serverConfig.baseDir,\n version: targetVersion,\n fs,\n path,\n runner,\n validate: (runtime) =>\n runner\n .run({\n command: execPath,\n args: [\n runtime.entryPath,\n \"__service-preflight\",\n \"--database-path\",\n serverConfig.dbPath,\n \"--launcher-protocol\",\n String(SERVICE_LAUNCHER_PROTOCOL),\n ],\n timeout: PREFLIGHT_TIMEOUT,\n })\n .pipe(\n Effect.mapError(\n (cause) =>\n new PinnedRuntimeInstallError({\n step: \"running the staged service preflight\",\n cause,\n }),\n ),\n Effect.flatMap(\n (\n result,\n ): Effect.Effect<\n void,\n PinnedRuntimeInstallError | PinnedRuntimePreflightBlockedError\n > => {\n if (result.code !== 0) {\n return Effect.fail(\n new PinnedRuntimeInstallError({\n step: \"running the staged service preflight\",\n exitCode: Number(result.code),\n stdoutLength: result.stdout.length,\n stderrLength: result.stderr.length,\n }),\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout.trim());\n } catch (cause) {\n return Effect.fail(\n new PinnedRuntimeInstallError({\n step: \"decoding the staged service preflight\",\n cause,\n }),\n );\n }\n const preflight = decodeServicePreflightResult(parsed);\n if (preflight === undefined || preflight.version !== targetVersion) {\n return Effect.fail(\n new PinnedRuntimeInstallError({\n step: \"verifying the staged service preflight\",\n }),\n );\n }\n return preflight.status === \"ready\"\n ? Effect.void\n : Effect.fail(\n new PinnedRuntimePreflightBlockedError({\n version: targetVersion,\n reason: preflight.reason,\n }),\n );\n },\n ),\n ),\n }).pipe(\n Effect.mapError((error) =>\n error._tag === \"PinnedRuntimePreflightBlockedError\"\n ? failWith(error.reason, error)\n : failWith(`Could not prepare t3@${targetVersion}.`, error),\n ),\n );\n\n yield* reportProgress(\"installing\");\n const updateId = yield* launcher\n .requestUpdate({ targetVersion, dbPath: serverConfig.dbPath })\n .pipe(\n Effect.mapError((error) =>\n failWith(\n error._tag === \"ServiceLauncherRejectedError\"\n ? error.reason\n : \"Could not ask the service launcher to activate the prepared update.\",\n error,\n ),\n ),\n );\n\n yield* Effect.logInfo(\"Server update prepared; handing off to the service launcher.\", {\n updateId,\n targetVersion,\n runtimePath: paths.entryPath,\n });\n return { targetVersion, method: \"boot-service\" as const, updateId };", + "checksum": "1cde992413bb70e3aa3870a47b638f195f71bea15ad23b31c52f713e142bcc06" + } +} diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro new file mode 100644 index 0000000..51bc38e --- /dev/null +++ b/src/layouts/BaseLayout.astro @@ -0,0 +1,52 @@ +--- +import cover from "../../cover.png"; +import "../styles/global.css"; +import "../styles/components.css"; + +interface Props { + title: string; + description: string; + canonicalPath?: string; +} + +const { title, description, canonicalPath = "" } = Astro.props; +const pageTitle = title === "T3 Code Decoded" ? title : `${title} · T3 Code Decoded`; +const canonical = Astro.site ? new URL(canonicalPath, Astro.site) : undefined; +const socialImage = Astro.site ? new URL(cover.src, Astro.site) : cover.src; +--- + + + + + + + + + + + + + + + + + + {canonical && } + {pageTitle} + + + + + + + diff --git a/src/layouts/BookLayout.astro b/src/layouts/BookLayout.astro new file mode 100644 index 0000000..b1391ee --- /dev/null +++ b/src/layouts/BookLayout.astro @@ -0,0 +1,365 @@ +--- +import type { MarkdownHeading } from "astro"; +import type { BookEntry } from "../lib/book"; +import { chapterLabel, entryHref, groupBookEntries, sortBookEntries } from "../lib/book"; +import lock from "../../sources/t3code.lock.json"; +import BaseLayout from "./BaseLayout.astro"; + +interface Props { + entry: BookEntry; + entries: BookEntry[]; + headings: MarkdownHeading[]; +} + +const { entry, entries, headings } = Astro.props; +const sorted = sortBookEntries(entries); +const groups = groupBookEntries(sorted); +const index = sorted.findIndex((candidate) => candidate.id === entry.id); +const previous = index > 0 ? sorted[index - 1] : undefined; +const next = index >= 0 && index < sorted.length - 1 ? sorted[index + 1] : undefined; +const sectionHeadings = headings.filter((heading) => heading.depth === 2 || heading.depth === 3); +const base = import.meta.env.BASE_URL; +const searchIndex = sorted.map((item) => ({ + title: item.data.title, + summary: item.data.summary, + part: item.data.part, + number: item.data.number ?? "", + keywords: item.data.keywords, + sourceAreas: item.data.sourceAreas, + url: entryHref(item, base), +})); +const readProgress = sorted.length === 0 ? 0 : ((index + 1) / sorted.length) * 100; +const snapshotDate = new Intl.DateTimeFormat("en-GB", { day: "numeric", month: "short", year: "numeric" }).format(new Date(lock.capturedAt)); +const tocIcon = (item: BookEntry) => { + if (item.data.kind === "front") return "↗"; + if (item.data.kind === "appendix") return "+"; + return "●"; +}; +const tocLabel = (item: BookEntry) => `${chapterLabel(item)}: ${item.data.title}`; +--- + + + +
    + + + + +
    +
    + +
    {entry.data.part}{entry.data.shortTitle ?? entry.data.title}
    +
    + + +
    +
    + +
    +
    +
    +
    + {chapterLabel(entry)} + {entry.data.status.replace("-", " ")} +
    +

    {entry.data.title}

    +

    {entry.data.summary}

    + {entry.data.objectives.length > 0 && ( +
    + What this chapter resolves +
      {entry.data.objectives.map((objective) =>
    • {objective}
    • )}
    +
    + )} +
    + +
    + +
    + +
    +
    + T3 +
    Source-locked editionRead against {lock.shortCommit} · {snapshotDate}
    +
    +
    +
    + + {sectionHeadings.length > 0 && ( + + )} +
    +
    +
    + + + + + +
    +
    + Book search +

    Find a concept, module, or source path

    +
    + +
    + +

    Type two or more characters.

    +
    +
    + + + +
    diff --git a/src/lib/book.ts b/src/lib/book.ts new file mode 100644 index 0000000..85a7530 --- /dev/null +++ b/src/lib/book.ts @@ -0,0 +1,30 @@ +import type { CollectionEntry } from "astro:content"; + +export type BookEntry = CollectionEntry<"book">; + +export const sortBookEntries = (entries: BookEntry[]) => + [...entries].sort((a, b) => a.data.order - b.data.order || a.data.title.localeCompare(b.data.title)); + +export const groupBookEntries = (entries: BookEntry[]) => { + const groups = new Map(); + for (const entry of sortBookEntries(entries)) { + const existing = groups.get(entry.data.part); + if (existing) existing.entries.push(entry); + else groups.set(entry.data.part, { order: entry.data.partOrder, entries: [entry] }); + } + return [...groups.entries()] + .sort((a, b) => a[1].order - b[1].order) + .map(([part, value]) => ({ part, ...value })); +}; + +export const entryHref = (entry: Pick, base = import.meta.env.BASE_URL) => { + const prefix = base.endsWith("/") ? base : `${base}/`; + return entry.data.slug === "cover" ? prefix : `${prefix}${entry.data.slug}/`; +}; + +export const chapterLabel = (entry: BookEntry) => { + if (entry.data.kind === "front") return "Start here"; + if (entry.data.kind === "appendix") return `Appendix ${entry.data.number ?? ""}`.trim(); + return `Chapter ${entry.data.number ?? ""}`.trim(); +}; + diff --git a/src/lib/diagram-explorer.ts b/src/lib/diagram-explorer.ts new file mode 100644 index 0000000..55d4bb3 --- /dev/null +++ b/src/lib/diagram-explorer.ts @@ -0,0 +1,247 @@ +const MIN_SCALE = 0.55; +const MAX_SCALE = 3; +const SCALE_STEP = 0.2; +const KEYBOARD_PAN_STEP = 48; + +const clamp = (value: number, minimum: number, maximum: number) => + Math.min(maximum, Math.max(minimum, value)); + +export function initDiagramExplorer(root: HTMLElement) { + if (root.dataset.diagramReady === "true") return; + root.dataset.diagramReady = "true"; + + const viewport = root.querySelector("[data-diagram-viewport]"); + const content = root.querySelector("[data-diagram-content]"); + const status = root.querySelector("[data-diagram-status]"); + const panButton = root.querySelector("[data-diagram-action='pan']"); + const zoomOutButton = root.querySelector("[data-diagram-action='zoom-out']"); + const zoomInButton = root.querySelector("[data-diagram-action='zoom-in']"); + const expandButton = root.querySelector("[data-diagram-action='expand']"); + const dialog = root.querySelector("[data-diagram-dialog]"); + const dialogHost = root.querySelector("[data-diagram-dialog-host]"); + const origin = root.querySelector("[data-diagram-origin]"); + const closeButton = root.querySelector("[data-diagram-close]"); + const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)"); + if (!viewport || !content || !origin) return; + + let scale = 1; + let translateX = 0; + let translateY = 0; + let panEnabled = false; + let activePointer: number | null = null; + let pointerX = 0; + let pointerY = 0; + let resizeObserver: ResizeObserver | undefined; + + const constrainPan = () => { + const viewportWidth = viewport.clientWidth; + const viewportHeight = viewport.clientHeight; + const scaledWidth = content.offsetWidth * scale; + const scaledHeight = content.offsetHeight * scale; + const expanded = root.dataset.diagramExpanded === "true"; + // A diagram often fits completely inside the larger dialog at 100%. Give + // that canvas bounded travel so Pan still means something before zooming. + const expandedTravelX = expanded && panEnabled ? viewportWidth * 0.45 : 0; + const expandedTravelY = expanded && panEnabled ? viewportHeight * 0.45 : 0; + const maxX = Math.max(expandedTravelX, (scaledWidth - viewportWidth) / 2); + const maxY = Math.max(expandedTravelY, (scaledHeight - viewportHeight) / 2); + translateX = clamp(translateX, -maxX, maxX); + translateY = clamp(translateY, -maxY, maxY); + }; + + const paint = (announce = false) => { + constrainPan(); + content.style.setProperty("--diagram-x", `${translateX}px`); + content.style.setProperty("--diagram-y", `${translateY}px`); + content.style.setProperty("--diagram-scale", String(scale)); + viewport.dataset.panEnabled = String(panEnabled); + panButton?.setAttribute("aria-pressed", String(panEnabled)); + panButton?.setAttribute("aria-label", panEnabled ? "Stop panning diagram" : "Pan diagram"); + zoomOutButton?.toggleAttribute("disabled", scale <= MIN_SCALE + 0.001); + zoomInButton?.toggleAttribute("disabled", scale >= MAX_SCALE - 0.001); + if (status) { + const value = `${Math.round(scale * 100)}% · pan ${panEnabled ? "on" : "off"}`; + status.value = value; + status.textContent = value; + if (!announce) status.setAttribute("aria-live", "off"); + else status.setAttribute("aria-live", "polite"); + } + }; + + const setPanEnabled = (enabled: boolean, announce = true) => { + panEnabled = enabled; + paint(announce); + }; + + const zoomTo = ( + requestedScale: number, + anchor?: { readonly clientX: number; readonly clientY: number }, + ) => { + const nextScale = clamp(requestedScale, MIN_SCALE, MAX_SCALE); + if (nextScale === scale) return; + if (anchor) { + const bounds = viewport.getBoundingClientRect(); + const pointX = anchor.clientX - bounds.left - bounds.width / 2; + const pointY = anchor.clientY - bounds.top - bounds.height / 2; + const ratio = nextScale / scale; + translateX = pointX - ratio * (pointX - translateX); + translateY = pointY - ratio * (pointY - translateY); + } + scale = Number(nextScale.toFixed(2)); + if (scale > 1) panEnabled = true; + paint(true); + }; + + const reset = () => { + scale = 1; + translateX = 0; + translateY = 0; + panEnabled = false; + paint(true); + }; + + const panBy = (x: number, y: number) => { + translateX += x; + translateY += y; + paint(false); + }; + + const restoreFromDialog = () => { + if (!origin.contains(viewport.closest("[data-diagram-surface]"))) { + const surface = root.querySelector("[data-diagram-surface]"); + if (surface) origin.append(surface); + } + root.dataset.diagramExpanded = "false"; + expandButton?.setAttribute("aria-expanded", "false"); + expandButton?.setAttribute("aria-label", "Expand diagram"); + requestAnimationFrame(() => paint(false)); + }; + + const toggleExpanded = () => { + if (!dialog || !dialogHost || typeof dialog.showModal !== "function") return; + if (dialog.open) { + dialog.close(); + return; + } + const surface = root.querySelector("[data-diagram-surface]"); + if (!surface) return; + dialogHost.append(surface); + root.dataset.diagramExpanded = "true"; + expandButton?.setAttribute("aria-expanded", "true"); + expandButton?.setAttribute("aria-label", "Exit expanded diagram"); + dialog.showModal(); + requestAnimationFrame(() => { + paint(false); + closeButton?.focus(); + }); + }; + + root.querySelectorAll("[data-diagram-action]").forEach((button) => { + button.addEventListener("click", () => { + switch (button.dataset.diagramAction) { + case "pan": + setPanEnabled(!panEnabled); + break; + case "zoom-out": + zoomTo(scale - SCALE_STEP); + break; + case "reset": + reset(); + break; + case "zoom-in": + zoomTo(scale + SCALE_STEP); + break; + case "expand": + toggleExpanded(); + break; + } + }); + }); + + viewport.addEventListener("wheel", (event) => { + if (event.ctrlKey || event.metaKey) { + event.preventDefault(); + const direction = event.deltaY > 0 ? -SCALE_STEP : SCALE_STEP; + zoomTo(scale + direction, { clientX: event.clientX, clientY: event.clientY }); + return; + } + const expanded = root.dataset.diagramExpanded === "true"; + if (!panEnabled || (scale <= 1 && !expanded)) return; + event.preventDefault(); + panBy(-event.deltaX, -event.deltaY); + }, { passive: false }); + + viewport.addEventListener("pointerdown", (event) => { + if (!panEnabled || event.button !== 0) return; + activePointer = event.pointerId; + pointerX = event.clientX; + pointerY = event.clientY; + viewport.setPointerCapture(event.pointerId); + viewport.dataset.dragging = "true"; + event.preventDefault(); + }); + viewport.addEventListener("pointermove", (event) => { + if (activePointer !== event.pointerId) return; + const x = event.clientX - pointerX; + const y = event.clientY - pointerY; + pointerX = event.clientX; + pointerY = event.clientY; + panBy(x, y); + }); + const endPointer = (event: PointerEvent) => { + if (activePointer !== event.pointerId) return; + activePointer = null; + viewport.dataset.dragging = "false"; + if (viewport.hasPointerCapture(event.pointerId)) viewport.releasePointerCapture(event.pointerId); + }; + viewport.addEventListener("pointerup", endPointer); + viewport.addEventListener("pointercancel", endPointer); + + viewport.addEventListener("keydown", (event) => { + if (event.key === "+" || event.key === "=") { + event.preventDefault(); + zoomTo(scale + SCALE_STEP); + } else if (event.key === "-" || event.key === "_") { + event.preventDefault(); + zoomTo(scale - SCALE_STEP); + } else if (event.key === "0") { + event.preventDefault(); + reset(); + } else if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + setPanEnabled(!panEnabled); + } else if (event.key === "Escape") { + if (dialog?.open) dialog.close(); + else setPanEnabled(false); + } else if (panEnabled && event.key.startsWith("Arrow")) { + event.preventDefault(); + const x = event.key === "ArrowLeft" ? KEYBOARD_PAN_STEP : event.key === "ArrowRight" ? -KEYBOARD_PAN_STEP : 0; + const y = event.key === "ArrowUp" ? KEYBOARD_PAN_STEP : event.key === "ArrowDown" ? -KEYBOARD_PAN_STEP : 0; + panBy(x, y); + } + }); + + dialog?.addEventListener("close", () => { + restoreFromDialog(); + expandButton?.focus(); + }); + closeButton?.addEventListener("click", () => dialog?.close()); + + const updateMotionPreference = () => { + content.dataset.reducedMotion = String(reduceMotion.matches); + }; + reduceMotion.addEventListener("change", updateMotionPreference); + updateMotionPreference(); + + if ("ResizeObserver" in window) { + resizeObserver = new ResizeObserver(() => paint(false)); + resizeObserver.observe(viewport); + } + + window.addEventListener("pagehide", () => { + resizeObserver?.disconnect(); + reduceMotion.removeEventListener("change", updateMotionPreference); + }, { once: true }); + + paint(false); +} diff --git a/src/lib/lab-motion.ts b/src/lib/lab-motion.ts new file mode 100644 index 0000000..4217d90 --- /dev/null +++ b/src/lib/lab-motion.ts @@ -0,0 +1,54 @@ +export const LAB_MOTION = { + detail: 220, + playbackLead: 760, + playbackStep: 1050, +} as const; + +export const animateLabPanel = ( + target: HTMLElement | null, + direction: number, + reduced: boolean, +) => { + if (!target || reduced) return undefined; + return target.animate( + [ + { opacity: 0.35, transform: `translateX(${direction * 12}px)` }, + { opacity: 1, transform: "translateX(0)" }, + ], + { duration: LAB_MOTION.detail, easing: "cubic-bezier(.2,.8,.2,1)" }, + ); +}; + +export const setPlaybackState = (button: HTMLButtonElement | null, playing: boolean, label: string) => { + if (!button) return; + button.setAttribute("aria-pressed", String(playing)); + button.textContent = playing ? `Pause ${label}` : `Play ${label}`; +}; + +export const handleRovingKeys = ( + event: KeyboardEvent, + nodes: HTMLButtonElement[], + currentIndex: number, + select: (index: number) => void, +) => { + const requested = (() => { + switch (event.key) { + case "ArrowLeft": + case "ArrowUp": + return Math.max(0, currentIndex - 1); + case "ArrowRight": + case "ArrowDown": + return Math.min(nodes.length - 1, currentIndex + 1); + case "Home": + return 0; + case "End": + return nodes.length - 1; + default: + return undefined; + } + })(); + if (requested === undefined || requested === currentIndex) return; + event.preventDefault(); + select(requested); + nodes[requested]?.focus(); +}; diff --git a/src/lib/sources.ts b/src/lib/sources.ts new file mode 100644 index 0000000..d1abee6 --- /dev/null +++ b/src/lib/sources.ts @@ -0,0 +1,40 @@ +import excerptManifest from "../../sources/excerpts.manifest.json"; +import lock from "../../sources/t3code.lock.json"; +import referenceManifest from "../../sources/references.manifest.json"; + +export interface SourceReference { + id: string; + path: string; + start?: number; + end?: number; + kind: "file" | "directory"; + label: string; +} + +const references = [ + ...excerptManifest.map((entry) => ({ ...entry, kind: "file" as const })), + ...referenceManifest, +] satisfies SourceReference[]; + +const catalog = new Map(references.map((reference) => [reference.id, reference])); + +export const getSourceReference = (id: string) => { + const reference = catalog.get(id); + if (!reference) throw new Error(`Unknown source reference: ${id}`); + return reference; +}; + +export const sourceReferenceLabel = (reference: SourceReference) => { + const lines = reference.start + ? `:${reference.start}${reference.end ? `–${reference.end}` : ""}` + : ""; + return `${reference.path}${lines}`; +}; + +export const sourceReferenceHref = (reference: SourceReference) => { + const route = reference.kind === "directory" ? "tree" : "blob"; + const lines = reference.kind === "file" && reference.start + ? `#L${reference.start}${reference.end ? `-L${reference.end}` : ""}` + : ""; + return `${lock.repository}/${route}/${lock.commit}/${reference.path}${lines}`; +}; diff --git a/src/pages/404.astro b/src/pages/404.astro new file mode 100644 index 0000000..d7c18e2 --- /dev/null +++ b/src/pages/404.astro @@ -0,0 +1,13 @@ +--- +import BaseLayout from "../layouts/BaseLayout.astro"; +const base = import.meta.env.BASE_URL; +--- + + +
    +

    404 · Outside the map

    +

    This chapter is not in the source tree.

    +

    The book may have moved while its evidence was being updated.

    + Return to the cover +
    +
    diff --git a/src/pages/[slug].astro b/src/pages/[slug].astro new file mode 100644 index 0000000..5f8166b --- /dev/null +++ b/src/pages/[slug].astro @@ -0,0 +1,19 @@ +--- +import { getCollection, render } from "astro:content"; +import BookLayout from "../layouts/BookLayout.astro"; + +export async function getStaticPaths() { + const entries = await getCollection("book"); + return entries + .filter((entry) => entry.data.slug !== "cover") + .map((entry) => ({ params: { slug: entry.data.slug }, props: { entry, entries } })); +} + +const { entry, entries } = Astro.props; +const { Content, headings } = await render(entry); +--- + + + + + diff --git a/src/pages/index.astro b/src/pages/index.astro new file mode 100644 index 0000000..a183b95 --- /dev/null +++ b/src/pages/index.astro @@ -0,0 +1,14 @@ +--- +import { getCollection, render } from "astro:content"; +import BookLayout from "../layouts/BookLayout.astro"; + +const entries = await getCollection("book"); +const entry = entries.find((candidate) => candidate.data.slug === "cover"); +if (!entry) throw new Error("The book requires a cover entry."); +const { Content, headings } = await render(entry); +--- + + + + + diff --git a/src/styles/components.css b/src/styles/components.css new file mode 100644 index 0000000..214af29 --- /dev/null +++ b/src/styles/components.css @@ -0,0 +1,371 @@ +.callout { + position: relative; + margin: 30px 0; + padding: 19px 21px 19px 54px; + border: 1px solid var(--line); + border-radius: 11px; + background: var(--paper-raised); + color: var(--ink-soft); + font-size: 16px; + line-height: 1.58; +} +.callout::before { + position: absolute; + top: 18px; + left: 18px; + display: grid; + width: 23px; + height: 23px; + place-items: center; + border-radius: 7px; + background: var(--signal-soft); + color: var(--signal-deep); + content: "i"; + font: 800 12px/1 var(--font-ui); +} +.callout.warning::before { background: color-mix(in srgb, var(--yellow) 18%, transparent); color: var(--yellow); content: "!"; } +.callout.success::before { background: color-mix(in srgb, var(--green) 16%, transparent); color: var(--green); content: "✓"; } +.callout strong.callout-title { display: block; margin-bottom: 5px; color: var(--ink); font: 750 11px/1.2 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; } +.callout > :last-child { margin-bottom: 0; } + +.source-excerpt { margin: 32px 0; overflow: hidden; border: 1px solid var(--navy-line); border-radius: 11px; background: var(--navy); color: var(--navy-text); box-shadow: 0 18px 45px rgb(5 9 16 / 17%); } +.source-caption { display: flex; gap: 12px; align-items: center; min-height: 48px; padding: 9px 13px; border-bottom: 1px solid var(--navy-line); background: var(--navy-raised); font-family: var(--font-ui); } +.source-dots { display: flex; gap: 5px; flex: none; } +.source-dots i { width: 8px; height: 8px; border-radius: 50%; background: #5e6879; } +.source-dots i:first-child { background: var(--signal); } +.source-path { min-width: 0; overflow: hidden; color: var(--navy-muted) !important; font: 550 10px/1.3 var(--font-mono); text-overflow: ellipsis; white-space: nowrap; text-decoration: none; } +.source-path:hover { color: #fff !important; } +.source-kind { flex: none; margin-left: auto; padding: 4px 7px; border: 1px solid #43516a; border-radius: 999px; color: #b8c4d7; font: 700 8px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; } +.source-copy { flex: none; border: 0; background: transparent; color: var(--navy-muted); cursor: pointer; font: 650 9px/1 var(--font-ui); } +.source-copy:hover { color: #fff; } +.source-scroll { overflow-x: auto; padding: 13px 0; } +.source-excerpt pre { margin: 0; min-width: max-content; font: 400 12px/1.68 var(--font-mono); tab-size: 2; } +.source-excerpt code { display: block; } +.source-line { display: grid; grid-template-columns: 54px minmax(0, 1fr); min-height: 20px; padding: 0 18px 0 0; } +.source-line::before { padding-right: 15px; color: #607088; content: attr(data-line); text-align: right; user-select: none; } +.source-line.is-focus { background: rgb(227 27 35 / 14%); box-shadow: inset 3px 0 var(--signal); } +.source-note { padding: 13px 17px 14px; border-top: 1px solid var(--navy-line); color: #c4cedc; font: 400 12px/1.5 var(--font-ui); } +.source-note strong { color: #fff; } + +.source-list { margin: 27px 0; border-top: 1px solid var(--line); } +.source-list h3 { margin: 18px 0 9px; color: var(--ink-faint); font: 750 10px/1 var(--font-ui); letter-spacing: .11em; text-transform: uppercase; } +.source-list a { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 13px; padding: 9px 0; border-bottom: 1px solid var(--line); color: var(--ink-soft); font: 500 12px/1.4 var(--font-ui); text-decoration: none; } +.source-list a:hover { color: var(--signal-deep); } +.source-list code { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.source-list span { color: var(--ink-faint); font-size: 10px; } + +.figure { margin: 34px 0; overflow: hidden; border: 1px solid var(--navy-line); border-radius: 12px; background: var(--navy); color: var(--navy-text); } +.figure-head { display: flex; gap: 14px; justify-content: space-between; align-items: baseline; padding: 11px 15px; border-bottom: 1px solid var(--navy-line); background: var(--navy-raised); font-family: var(--font-ui); } +.figure-head strong { font-size: 10px; letter-spacing: .09em; text-transform: uppercase; } +.figure-head span { color: var(--navy-muted); font-size: 9px; } +.figure-body { padding: 18px; } +.figure figcaption { padding: 12px 16px 14px; border-top: 1px solid var(--navy-line); color: var(--navy-muted); font: 400 11px/1.5 var(--font-ui); } +.figure figcaption strong { color: var(--navy-text); } +.figure-text { padding: 10px 16px; border-top: 1px solid var(--navy-line); color: var(--navy-muted); font: 400 11px/1.5 var(--font-ui); } +.figure-text summary { color: var(--navy-text); cursor: pointer; font-weight: 700; } +.figure-text p { margin: 8px 0 2px; } +.figure-sources { display: flex; flex-wrap: wrap; gap: 7px 14px; padding: 10px 16px 13px; border-top: 1px solid var(--navy-line); font: 500 9px/1.35 var(--font-ui); } +.figure-sources a { color: var(--navy-muted) !important; text-decoration: none; } +.figure-sources a:hover { color: var(--navy-text) !important; } +.diagram-explorer { min-width: 0; } +.diagram-surface { min-width: 0; } +.diagram-toolbar { + display: none; + grid-template-columns: minmax(0, 1fr) auto auto; + gap: 12px; + align-items: center; + margin-bottom: 10px; + color: var(--navy-muted); + font-family: var(--font-ui); +} +.js .diagram-explorer[data-diagram-state="ready"] .diagram-toolbar { display: grid; } +.diagram-toolbar > strong { overflow: hidden; color: var(--navy-text); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; } +.diagram-actions { display: flex; gap: 5px; align-items: center; } +.diagram-actions button, +.diagram-close { + display: inline-flex; + gap: 6px; + align-items: center; + justify-content: center; + min-width: 44px; + min-height: 44px; + padding: 0 10px; + border: 1px solid var(--navy-line); + border-radius: 8px; + background: var(--navy-raised); + color: var(--navy-text); + cursor: pointer; + font: 700 10px/1 var(--font-ui); +} +.diagram-actions button:hover, +.diagram-close:hover { border-color: var(--signal); background: #1b2537; } +.diagram-actions button[aria-pressed="true"] { border-color: var(--signal); background: color-mix(in srgb, var(--signal) 18%, var(--navy-raised)); } +.diagram-actions button:disabled { cursor: not-allowed; opacity: .42; } +.diagram-status { min-width: 92px; color: var(--navy-muted); font: 650 9px/1 var(--font-mono); text-align: right; } +.diagram-viewport { + min-width: 0; + min-height: 220px; + overflow: hidden; + border: 1px solid color-mix(in srgb, var(--navy-line) 78%, transparent); + border-radius: 9px; + background: color-mix(in srgb, var(--navy-raised) 36%, transparent); + cursor: default; + outline: none; + touch-action: pan-y pinch-zoom; +} +.diagram-viewport:focus-visible { outline: 3px solid var(--signal); outline-offset: 3px; } +.diagram-viewport[data-pan-enabled="true"] { cursor: grab; touch-action: none; } +.diagram-viewport[data-dragging="true"] { cursor: grabbing; user-select: none; } +.mermaid { + --diagram-scale: 1; + --diagram-x: 0px; + --diagram-y: 0px; + display: flex; + min-width: 100%; + min-height: 218px; + align-items: center; + justify-content: center; + margin: 0; + padding: 12px; + overflow: visible; + box-sizing: border-box; + background: transparent; + transform: translate3d(var(--diagram-x), var(--diagram-y), 0) scale(var(--diagram-scale)); + transform-origin: center; + transition: transform var(--motion-fast) var(--motion-ease); +} +.mermaid[data-reduced-motion="true"], +.diagram-viewport[data-dragging="true"] .mermaid { transition: none; } +.mermaid svg { max-width: 100%; height: auto; } +.diagram-help { display: none; margin: 9px 2px 0; color: var(--navy-muted); font: 500 10px/1.45 var(--font-ui); } +.js .diagram-explorer[data-diagram-state="ready"] .diagram-help { display: block; } +.diagram-help kbd { padding: 1px 4px; border: 1px solid var(--navy-line); border-radius: 4px; background: var(--navy-raised); color: var(--navy-text); font: 650 9px/1.2 var(--font-mono); } +html:not(.js) .diagram-viewport, +.diagram-explorer[data-diagram-state="error"] .diagram-viewport { overflow: auto; } +html:not(.js) .mermaid, +.diagram-explorer[data-diagram-state="error"] .mermaid { display: block; min-width: max-content; white-space: pre; } +.diagram-dialog { + width: calc(100vw - 32px); + max-width: 1500px; + height: calc(100dvh - 32px); + max-height: 1000px; + padding: 0; + overflow: hidden; + border: 1px solid var(--navy-line); + border-radius: 14px; + background: var(--navy); + color: var(--navy-text); + box-shadow: 0 28px 90px rgb(0 0 0 / 45%); +} +.diagram-dialog::backdrop { background: rgb(4 8 15 / 76%); backdrop-filter: blur(4px); } +.diagram-dialog-shell { display: flex; height: 100%; min-height: 0; flex-direction: column; } +.diagram-dialog-shell > header { display: flex; gap: 16px; align-items: center; justify-content: space-between; padding: 10px 12px 10px 18px; border-bottom: 1px solid var(--navy-line); background: var(--navy-raised); font: 700 12px/1.2 var(--font-ui); } +.diagram-close { flex: none; } +.diagram-dialog-host { min-height: 0; flex: 1; padding: 14px; } +.diagram-dialog-host > .diagram-surface { display: flex; height: 100%; min-height: 0; flex-direction: column; } +.diagram-dialog-host .diagram-viewport { min-height: 0; flex: 1; } +.diagram-dialog-host .diagram-help { flex: none; } + +.layer-map { display: grid; gap: 8px; } +.layer-row { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 12px; align-items: stretch; } +.layer-label { display: flex; align-items: center; justify-content: flex-end; color: var(--navy-muted); font: 700 9px/1.2 var(--font-ui); letter-spacing: .1em; text-align: right; text-transform: uppercase; } +.layer-nodes { display: flex; flex-wrap: wrap; gap: 7px; } +.layer-node { flex: 1 1 120px; min-width: 105px; padding: 10px 11px; border: 1px solid #3a485f; border-radius: 8px; background: var(--navy-raised); color: var(--navy-text) !important; font: 650 11px/1.28 var(--font-ui); text-align: center; text-decoration: none; } +.layer-node:hover, .layer-node:focus-visible { border-color: var(--signal); background: #1b2537; } +.layer-row.boundary .layer-nodes { padding: 6px; border: 1px dashed #6b3340; border-radius: 10px; background: rgb(227 27 35 / 7%); } +.layer-row.tone-client .layer-node { border-color: #336b9c; } +.layer-row.tone-transport .layer-node { border-color: #2d79a7; background: #0d2538; } +.layer-row.tone-durable .layer-node { border-color: #a87822; background: #2a2111; } +.layer-row.tone-runtime .layer-node { border-color: #9c4f57; background: #291719; } +.layer-row.tone-external .layer-node { border-color: #387d65; background: #10261f; } + +.stat-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 28px 0; } +.stat { padding: 18px; border-top: 3px solid var(--signal); background: var(--paper-raised); box-shadow: inset 0 0 0 1px var(--line); } +.stat strong { display: block; color: var(--ink); font: 760 26px/1 var(--font-display); letter-spacing: -.04em; } +.stat span { display: block; margin-top: 6px; color: var(--ink-faint); font: 600 10px/1.3 var(--font-ui); letter-spacing: .07em; text-transform: uppercase; } + +.comparison { width: 100%; margin: 27px 0; border-collapse: collapse; font-family: var(--font-ui); font-size: 13px; line-height: 1.45; } +.comparison th, .comparison td { padding: 11px 12px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; } +.comparison th { color: var(--ink-faint); font-size: 10px; letter-spacing: .06em; text-transform: uppercase; } +.comparison td:first-child { color: var(--ink); font-weight: 700; } +.table-scroll { overflow-x: auto; } +.table-scroll:focus-visible { outline: 3px solid var(--signal); outline-offset: 3px; } + +.decision-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 29px 0; } +.decision { padding: 18px; border: 1px solid var(--line); border-radius: 10px; background: var(--paper-raised); } +.decision .decision-label { color: var(--signal-deep); font: 750 9px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase; } +.decision h3 { margin: 9px 0 8px; font-size: 18px; } +.decision p { margin: 0; color: var(--ink-soft); font: 400 13px/1.55 var(--font-ui); } + +.book-cover { margin-top: -18px; } +.cover-stage { position: relative; display: grid; grid-template-columns: minmax(240px, 420px) minmax(220px, 1fr); gap: 44px; align-items: center; } +.cover-art { overflow: hidden; border-radius: 4px; background: #fff; box-shadow: 0 28px 80px rgb(16 19 26 / 20%); } +.cover-art img { width: 100%; height: auto; } +.cover-copy .cover-mark { color: var(--signal-deep); font: 750 10px/1 var(--font-ui); letter-spacing: .17em; text-transform: uppercase; } +.cover-copy h2 { margin: 14px 0 16px; font-size: clamp(36px, 5vw, 58px); } +.cover-copy p { color: var(--ink-soft); font-size: 19px; line-height: 1.55; } +.cover-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; } +.cover-meta { display: grid; gap: 7px; margin-top: 30px; padding-top: 18px; border-top: 1px solid var(--line); color: var(--ink-faint); font: 550 10px/1.35 var(--font-ui); } + +.trace-lab { margin: 34px 0; border: 1px solid var(--line); border-radius: 13px; background: var(--paper-raised); overflow: hidden; } +.trace-head { padding: 18px 20px 14px; } +.trace-head > span { color: var(--signal-deep); font: 800 9px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase; } +.trace-head h3 { margin: 8px 0 5px; } +.trace-head p { margin: 0; color: var(--ink-soft); font: 400 13px/1.5 var(--font-ui); } +.trace-controls { display: none; flex-wrap: wrap; gap: 10px; align-items: center; padding: 12px; border-bottom: 1px solid var(--line); } +.js .trace-controls { display: flex; } +.trace-controls button { min-height: 44px; padding: 0 13px; border: 1px solid var(--line); border-radius: 7px; background: var(--paper); cursor: pointer; color: var(--ink-soft); font: 700 11px/1 var(--font-ui); } +.trace-controls button:hover { border-color: var(--signal); color: var(--ink); } +.trace-controls button:disabled { cursor: not-allowed; opacity: .45; } +.trace-counter { margin-left: auto; color: var(--ink-faint); font: 650 10px/1 var(--font-mono); } +.trace-progress { display: none; height: 4px; overflow: hidden; background: var(--paper-muted); } +.js .trace-progress { display: block; } +.trace-progress span { display: block; width: var(--trace-progress); height: 100%; background: var(--signal); transition: width var(--motion-flow) var(--motion-ease); } +.trace-track { display: none; grid-template-columns: repeat(6, 1fr); gap: 4px; margin: 0; padding: 15px; border-bottom: 1px solid var(--line); list-style: none; } +.js .trace-track { display: grid; } +.trace-track > li { min-width: 0; } +.trace-node { position: relative; display: grid; width: 100%; min-height: 70px; padding: 10px 6px; place-items: center; border: 1px solid var(--line); border-radius: 8px; background: var(--paper); color: var(--ink-faint); cursor: pointer; font: 650 10px/1.3 var(--font-ui); text-align: center; transition: border-color var(--motion-fast) ease, background var(--motion-fast) ease, color var(--motion-fast) ease, transform var(--motion-fast) ease; } +.trace-node.passed { border-color: color-mix(in srgb, var(--signal) 40%, var(--line)); color: var(--ink-soft); } +.trace-node.passed::after { position: absolute; top: 6px; right: 7px; color: var(--signal-deep); content: "✓"; font-size: 9px; } +.trace-node.active { transform: translateY(-2px); border-color: var(--signal); background: var(--signal-soft); color: var(--ink); box-shadow: inset 0 -3px var(--signal); } +.trace-detail { display: none; min-height: 185px; padding: 22px; } +.js .trace-detail { display: block; } +.trace-detail .step { color: var(--signal-deep); font: 750 10px/1 var(--font-ui); letter-spacing: .11em; text-transform: uppercase; } +.trace-detail h3 { margin: 10px 0; font-size: 23px; } +.trace-detail p { margin-bottom: 0; color: var(--ink-soft); font-size: 15px; } +.trace-detail code { font-size: 11px; } +.trace-detail [data-trace-source] { display: inline-block; margin-top: 14px; color: var(--signal-deep); font: 600 11px/1.4 var(--font-ui); text-decoration: none; } +.trace-print { display: block; margin: 0; padding: 18px 28px 18px 42px; } +.js .trace-print { display: none; } + +.evidence-claim { margin: 30px 0; overflow: hidden; border: 1px solid var(--line); border-left: 4px solid var(--blue); border-radius: 10px; background: var(--paper-raised); } +.evidence-claim.is-documented { border-left-color: var(--purple); } +.evidence-claim.is-inference { border-left-color: var(--orange); } +.evidence-claim.is-future { border-left-color: var(--ink-faint); border-style: dashed; } +.evidence-claim-head { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: baseline; padding: 12px 15px; border-bottom: 1px solid var(--line); font-family: var(--font-ui); } +.evidence-claim-head span { color: var(--blue); font-size: 9px; font-weight: 800; letter-spacing: .11em; text-transform: uppercase; } +.evidence-claim.is-documented .evidence-claim-head span { color: var(--purple); } +.evidence-claim.is-inference .evidence-claim-head span { color: var(--orange); } +.evidence-claim.is-future .evidence-claim-head span { color: var(--ink-faint); } +.evidence-claim-head strong { font-size: 13px; } +.evidence-claim-body { padding: 15px; color: var(--ink-soft); font-size: 15px; } +.evidence-claim-body > :last-child { margin-bottom: 0; } +.evidence-claim-sources { display: grid; gap: 5px; padding: 10px 15px 13px; border-top: 1px solid var(--line); font: 500 9px/1.35 var(--font-ui); } +.evidence-claim-sources a { overflow-wrap: anywhere; color: var(--signal-deep); text-decoration: none; } + +.scenario-lab { margin: 34px 0; overflow: hidden; border: 1px solid var(--line); border-radius: 13px; background: var(--paper-raised); } +.scenario-head { padding: 18px 20px 13px; } +.scenario-head > span { color: var(--signal-deep); font: 800 9px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase; } +.scenario-head h3 { margin: 8px 0 5px; } +.scenario-head p { margin: 0; color: var(--ink-soft); font: 400 13px/1.5 var(--font-ui); } +.scenario-tabs { display: none; gap: 7px; overflow-x: auto; padding: 10px 12px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); } +.js .scenario-tabs { display: flex; } +.scenario-tabs button { flex: none; min-height: 44px; padding: 0 14px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink-soft); cursor: pointer; font: 700 10px/1 var(--font-ui); transition: border-color var(--motion-fast) ease, background var(--motion-fast) ease, color var(--motion-fast) ease, transform var(--motion-fast) ease; } +.scenario-tabs button[aria-selected="true"] { transform: translateY(-1px); border-color: var(--signal); background: var(--signal-soft); color: var(--ink); } +.scenario-detail { display: none; padding: 20px; border-left: 4px solid var(--blue); transition: border-color var(--motion-detail) ease; } +.js .scenario-detail { display: block; } +.scenario-detail.tone-safe { border-left-color: var(--green); } +.scenario-detail.tone-warning { border-left-color: var(--orange); } +.scenario-detail.tone-failure { border-left-color: var(--signal); } +.scenario-meta { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; } +.scenario-meta > span { color: var(--signal-deep); font: 800 9px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase; } +.scenario-meta > strong { color: var(--ink-faint); font: 750 9px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; } +.scenario-detail h4 { margin: 7px 0 8px; font: 740 21px/1.2 var(--font-display); } +.scenario-detail > p, .scenario-detail li { color: var(--ink-soft); font-size: 14px; } +.scenario-detail > p { margin-bottom: 10px; } +.scenario-detail ul { margin-bottom: 12px; } +.scenario-sources { display: grid; gap: 4px; padding-top: 10px; border-top: 1px solid var(--line); font: 500 9px/1.35 var(--font-ui); } +.scenario-sources a { overflow-wrap: anywhere; color: var(--signal-deep); text-decoration: none; } +.scenario-print { display: block; padding: 18px 28px 18px 42px; } +.js .scenario-print { display: none; } + +.flow-lab { margin: 34px 0; overflow: hidden; border: 1px solid var(--line); border-radius: 13px; background: var(--paper-raised); } +.flow-head { padding: 18px 20px 14px; } +.flow-head > span { color: var(--signal-deep); font: 800 9px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase; } +.flow-head h3 { margin: 8px 0 5px; } +.flow-head p { margin: 0; color: var(--ink-soft); font: 400 13px/1.5 var(--font-ui); } +.flow-controls { display: none; flex-wrap: wrap; gap: 9px; align-items: center; padding: 11px 12px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); } +.js .flow-controls { display: flex; } +.flow-controls button { min-height: 44px; padding: 0 13px; border: 1px solid var(--line); border-radius: 7px; background: var(--paper); color: var(--ink-soft); cursor: pointer; font: 700 10px/1 var(--font-ui); } +.flow-controls [data-flow-play] { border-color: var(--signal); color: var(--signal-deep); } +.flow-controls button:hover { border-color: var(--signal); color: var(--ink); } +.flow-controls button:disabled { cursor: not-allowed; opacity: .45; } +.flow-counter { margin-left: auto; color: var(--ink-faint); font: 650 10px/1 var(--font-mono); } +.flow-viewport { display: none; overflow-x: auto; overscroll-behavior-inline: contain; padding: 0 10px; scrollbar-width: thin; } +.js .flow-viewport { display: block; } +.flow-track-shell { position: relative; min-width: max(100%, calc(var(--flow-count) * 110px)); } +.flow-track { display: grid; grid-template-columns: repeat(var(--flow-count), minmax(98px, 1fr)); gap: 9px; margin: 0; padding: 27px 0 14px; list-style: none; } +.flow-track > li { min-width: 0; } +.flow-rail { position: absolute; top: 48px; height: 2px; background: var(--line-strong); } +.flow-rail span { display: block; width: 0; height: 100%; background: var(--signal); transition: width var(--motion-flow) var(--motion-ease); } +.flow-token { position: absolute; z-index: 3; top: 41px; left: -7px; width: 14px; height: 14px; border: 3px solid var(--paper-raised); border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 1px var(--signal); transition: transform var(--motion-flow) var(--motion-ease); } +.flow-token i { position: absolute; inset: 3px; border-radius: 50%; background: var(--paper-raised); } +.flow-node { position: relative; z-index: 2; display: grid; gap: 8px; justify-items: center; min-height: 74px; padding: 7px 6px 8px; border: 0; background: transparent; color: var(--ink-faint); cursor: pointer; font-family: var(--font-ui); } +.flow-node > span { display: grid; width: 28px; height: 28px; place-items: center; border: 2px solid var(--line-strong); border-radius: 50%; background: var(--paper-raised); color: var(--ink-faint); font: 800 9px/1 var(--font-mono); transition: border-color var(--motion-detail) ease, background var(--motion-detail) ease, color var(--motion-detail) ease, transform var(--motion-detail) ease; } +.flow-node strong { max-width: 14ch; color: inherit; font: 700 10px/1.25 var(--font-ui); text-align: center; } +.flow-node.passed > span { border-color: var(--signal); color: var(--signal-deep); } +.flow-node.active { color: var(--ink); } +.flow-node.active > span { transform: scale(1.12); border-color: var(--signal); background: var(--signal-soft); color: var(--signal-deep); } +.flow-node.tone-durable.active > span { border-color: var(--green); background: color-mix(in srgb, var(--green) 13%, var(--paper-raised)); color: var(--green); } +.flow-node.tone-transport.active > span, .flow-node.tone-client.active > span { border-color: var(--blue); background: color-mix(in srgb, var(--blue) 12%, var(--paper-raised)); color: var(--blue); } +.flow-node.tone-runtime.active > span, .flow-node.tone-side-effect.active > span { border-color: var(--orange); background: color-mix(in srgb, var(--orange) 12%, var(--paper-raised)); color: var(--orange); } +.flow-node.tone-failure.active > span { border-color: var(--signal); color: var(--signal-deep); } +.flow-detail { display: none; min-height: 190px; padding: 20px; border-top: 1px solid var(--line); border-left: 4px solid var(--blue); transition: border-color var(--motion-detail) ease; } +.js .flow-detail { display: block; } +.flow-detail.tone-durable { border-left-color: var(--green); } +.flow-detail.tone-runtime, .flow-detail.tone-side-effect { border-left-color: var(--orange); } +.flow-detail.tone-failure { border-left-color: var(--signal); } +.flow-detail-meta { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; } +.flow-detail-meta span { color: var(--signal-deep); font: 800 9px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase; } +.flow-detail-meta strong { color: var(--ink-faint); font: 750 9px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; } +.flow-detail-meta code { color: var(--ink-faint); font-size: 10px; } +.flow-detail h4 { margin: 9px 0 8px; font: 740 21px/1.2 var(--font-display); } +.flow-detail > p { margin: 0 0 12px; color: var(--ink-soft); font-size: 14px; } +.flow-sources { display: grid; gap: 4px; padding-top: 10px; border-top: 1px solid var(--line); font: 500 9px/1.35 var(--font-ui); } +.flow-sources a { overflow-wrap: anywhere; color: var(--signal-deep); text-decoration: none; } +.flow-print { display: block; padding: 18px 28px 18px 42px; } +.js .flow-print { display: none; } + +@media (max-width: 720px) { + .cover-stage { grid-template-columns: 1fr; } + .cover-art { width: min(100%, 360px); } + .stat-grid, .decision-grid { grid-template-columns: 1fr; } + .layer-row { grid-template-columns: 1fr; } + .layer-label { justify-content: flex-start; text-align: left; } + .trace-track { grid-template-columns: repeat(3, 1fr); } + .flow-controls button { flex: 1 1 auto; } + .flow-counter { width: 100%; margin-left: 0; text-align: right; } + .source-caption { flex-wrap: wrap; } + .source-kind { margin-left: 0; } + .diagram-toolbar { grid-template-columns: 1fr auto; } + .diagram-status { grid-column: 1 / -1; min-width: 0; text-align: left; } + .diagram-actions { max-width: 100%; overflow-x: auto; padding: 2px; } + .diagram-actions button span + span { display: none; } + .diagram-help { font-size: 9px; } +} + +@media print { + .figure, .source-excerpt { break-inside: avoid; box-shadow: none; } + .figure-body, .source-excerpt, .source-caption, .source-note { background: #fff !important; color: #000 !important; } + .figure-head, .figure-text, .figure figcaption, .figure-sources { background: #fff; color: #000; } + .figure-text { display: block; } + .figure-text summary { list-style: none; } + .figure-text summary::after { content: ":"; } + .figure-sources a, .source-path, .source-kind, .source-note, .source-note strong { color: #000 !important; } + .diagram-toolbar, .diagram-help, .diagram-dialog { display: none !important; } + .diagram-viewport { min-height: 0; overflow: visible; border: 0; background: #fff; } + .mermaid { min-height: 0; padding: 0; transform: none !important; transition: none !important; } + .source-copy, .trace-controls, .trace-progress, .trace-track, .trace-detail { display: none !important; } + .source-line::before { color: #555; } + .source-line.is-focus { background: #eee; } + .js .trace-print { display: block; margin: 0; padding: 18px 28px 18px 42px; } + .trace-print li { break-inside: avoid; margin-bottom: 12px; } + .trace-print p { margin: 3px 0; } + .scenario-tabs, .scenario-detail { display: none !important; } + .js .scenario-print { display: block; padding: 18px 28px 18px 42px; } + .scenario-print > li { break-inside: avoid; margin-bottom: 14px; } + .flow-controls, .flow-viewport, .flow-detail { display: none !important; } + .js .flow-print { display: block; padding: 18px 28px 18px 42px; } + .flow-print > li { break-inside: avoid; margin-bottom: 14px; } + details:not([open]) > :not(summary) { display: block !important; } +} diff --git a/src/styles/global.css b/src/styles/global.css new file mode 100644 index 0000000..c19fc88 --- /dev/null +++ b/src/styles/global.css @@ -0,0 +1,515 @@ +:root { + color-scheme: light dark; + --paper: #f7f4ee; + --paper-raised: #fffdf8; + --paper-muted: #eee9df; + --ink: #10131a; + --ink-soft: #4b505b; + --ink-faint: #616671; + --line: #d9d3c8; + --line-strong: #b9b0a2; + --signal: #e31b23; + --signal-deep: #b51219; + --signal-soft: #fde6e4; + --navy: #091222; + --navy-raised: #111d30; + --navy-line: #2c3a51; + --navy-text: #f3f6fb; + --navy-muted: #aab5c6; + --blue: #075fae; + --orange: #e46f18; + --green: #08724e; + --purple: #7652c6; + --yellow: #d8a619; + --shadow: 0 18px 60px rgb(20 18 14 / 10%); + --motion-fast: 180ms; + --motion-detail: 220ms; + --motion-flow: 300ms; + --motion-ease: cubic-bezier(.2,.8,.2,1); + --font-display: "Avenir Next", "Segoe UI", system-ui, sans-serif; + --font-body: Charter, "Bitstream Charter", "Iowan Old Style", Georgia, serif; + --font-ui: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace; + --sidebar-expanded: 304px; + --sidebar-collapsed: 76px; + --sidebar: var(--sidebar-expanded); + --outline: 224px; + --measure: 780px; + --chapter-dock-reserve: 114px; +} + +:root[data-sidebar="collapsed"] { --sidebar: var(--sidebar-collapsed); } + +:root[data-theme="dark"] { + --paper: #0d1118; + --paper-raised: #151a23; + --paper-muted: #1d2430; + --ink: #f3f1ea; + --ink-soft: #c5c8ce; + --ink-faint: #9da3ad; + --line: #303744; + --line-strong: #4b5565; + --signal: #ff454b; + --signal-deep: #ff6c70; + --signal-soft: #391a1d; + --blue: #73baff; + --green: #63d4aa; + --shadow: 0 18px 60px rgb(0 0 0 / 32%); +} + +@media (prefers-color-scheme: dark) { + :root[data-theme="system"] { + --paper: #0d1118; + --paper-raised: #151a23; + --paper-muted: #1d2430; + --ink: #f3f1ea; + --ink-soft: #c5c8ce; + --ink-faint: #9da3ad; + --line: #303744; + --line-strong: #4b5565; + --signal: #ff454b; + --signal-deep: #ff6c70; + --signal-soft: #391a1d; + --blue: #73baff; + --green: #63d4aa; + --shadow: 0 18px 60px rgb(0 0 0 / 32%); + } +} + +*, *::before, *::after { box-sizing: border-box; } +html { scroll-behavior: smooth; scroll-padding-top: 84px; } +body { + margin: 0; + min-width: 320px; + background: var(--paper); + color: var(--ink); + font-family: var(--font-body); + font-size: 18px; + line-height: 1.72; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; +} +body.drawer-open { overflow: hidden; } +a { color: inherit; text-decoration-thickness: .08em; text-underline-offset: .15em; } +button, input { font: inherit; } +button { color: inherit; } +img { display: block; max-width: 100%; } +code, kbd, pre { font-family: var(--font-mono); } +code { font-size: .88em; } +::selection { background: var(--signal); color: #fff; } + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.skip-link { + position: fixed; + z-index: 200; + top: 10px; + left: 10px; + transform: translateY(-140%); + padding: 9px 14px; + border-radius: 8px; + background: var(--ink); + color: var(--paper); + font: 600 13px/1 var(--font-ui); + text-decoration: none; +} +.skip-link:focus { transform: none; } + +:focus-visible { outline: 3px solid color-mix(in srgb, var(--signal) 70%, transparent); outline-offset: 3px; } + +.reading-progress { + position: fixed; + inset: 0 0 auto 0; + height: 3px; + z-index: 140; + background: transparent; +} +.reading-progress span { display: block; height: 100%; background: var(--signal); transition: width .2s ease; } + +.book-shell { min-height: 100vh; } +.book-sidebar { + position: fixed; + inset: 0 auto 0 0; + z-index: 80; + width: var(--sidebar); + display: flex; + flex-direction: column; + background: var(--paper-raised); + border-right: 1px solid var(--line); + transition: width var(--motion-fast) var(--motion-ease); +} +.sidebar-head { padding: 27px 24px 22px; border-bottom: 1px solid var(--line); } +.sidebar-head-row { display: flex; gap: 10px; align-items: flex-start; justify-content: space-between; } +.sidebar-identity { min-width: 0; } +.imprint { + display: inline-flex; + color: var(--signal-deep); + font: 700 10px/1 var(--font-ui); + letter-spacing: .16em; + text-decoration: none; + text-transform: uppercase; +} +.book-title { + display: block; + margin-top: 11px; + color: var(--ink); + font: 750 25px/.98 var(--font-display); + letter-spacing: -.04em; + text-decoration: none; +} +.book-title-mark { display: none; } +.book-title-copy { color: var(--ink); } +.book-title-copy > span { color: var(--signal); } +.source-lock { + display: flex; + align-items: center; + gap: 7px; + margin-top: 11px; + color: var(--ink-faint); + font: 500 10px/1.3 var(--font-ui); + letter-spacing: .05em; + text-transform: uppercase; +} +.source-lock span { width: 7px; height: 7px; border-radius: 50%; background: var(--green); } +.source-lock code { font-size: 10px; text-transform: none; } +.sidebar-toggle { + flex: none; + width: 44px; + min-height: 44px; + padding: 0; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--paper-raised); + color: var(--ink-faint); + cursor: pointer; + font: 700 22px/1 var(--font-ui); +} +.sidebar-toggle:hover { border-color: var(--signal); color: var(--signal-deep); } +.book-toc { flex: 1; overflow-y: auto; padding: 12px 12px 38px; scrollbar-width: thin; } +.toc-part { margin: 0; } +.toc-part h2 { + margin: 18px 11px 7px; + color: var(--ink-faint); + font: 700 10px/1.2 var(--font-ui); + letter-spacing: .13em; + text-transform: uppercase; +} +.toc-link { + display: grid; + grid-template-columns: 37px minmax(0, 1fr); + gap: 7px; + align-items: baseline; + margin: 2px 0; + padding: 7px 10px; + border-left: 2px solid transparent; + border-radius: 7px; + color: var(--ink-soft); + font: 500 13px/1.35 var(--font-ui); + text-decoration: none; +} +.toc-link:hover { background: var(--paper-muted); color: var(--ink); } +.toc-link.active { border-left-color: var(--signal); background: var(--signal-soft); color: var(--ink); font-weight: 700; } +.toc-marker { display: inline-flex; gap: 5px; align-items: center; color: var(--ink-faint); font: 500 10px/1.3 var(--font-mono); } +.toc-icon { color: var(--signal-deep); font: 700 9px/1 var(--font-ui); } +.toc-number { font: inherit; } +.toc-link.active .toc-marker { color: var(--signal-deep); } +.toc-title { overflow: hidden; text-overflow: ellipsis; } +.sidebar-foot { padding: 13px 23px 18px; border-top: 1px solid var(--line); } +.sidebar-foot a { color: var(--ink-faint); font: 600 11px/1 var(--font-ui); text-decoration: none; } +.sidebar-foot a:hover { color: var(--signal-deep); } + +.sidebar-scrim { display: none; } +.sidebar-tooltip { + position: fixed; + z-index: 160; + max-width: min(300px, calc(100vw - 24px)); + padding: 7px 9px; + border: 1px solid var(--line-strong); + border-radius: 7px; + background: var(--ink); + color: var(--paper); + box-shadow: var(--shadow); + font: 650 11px/1.3 var(--font-ui); + pointer-events: none; +} +.book-main { min-width: 0; margin-left: var(--sidebar); transition: margin-left var(--motion-fast) var(--motion-ease); } +.book-toolbar { + position: sticky; + top: 0; + z-index: 60; + min-height: 58px; + display: flex; + align-items: center; + gap: 12px; + padding: 10px 24px; + border-bottom: 1px solid color-mix(in srgb, var(--line) 80%, transparent); + background: color-mix(in srgb, var(--paper) 88%, transparent); + backdrop-filter: blur(12px); +} +.toolbar-crumb { min-width: 0; display: flex; gap: 8px; align-items: baseline; font: 500 12px/1.2 var(--font-ui); } +.toolbar-crumb span { flex: none; color: var(--ink-faint); } +.toolbar-crumb strong { overflow: hidden; color: var(--ink-soft); text-overflow: ellipsis; white-space: nowrap; } +.toolbar-actions { display: flex; gap: 8px; align-items: center; margin-left: auto; } +.icon-button, .search-trigger { + min-height: 36px; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--paper-raised); + color: var(--ink-soft); + cursor: pointer; + font: 650 12px/1 var(--font-ui); +} +.icon-button { width: 38px; padding: 0; font-size: 17px; } +.search-trigger { display: flex; gap: 9px; align-items: center; padding: 0 10px; } +.search-trigger kbd { padding: 3px 6px; border: 1px solid var(--line); border-radius: 5px; color: var(--ink-faint); font-size: 9px; } +.icon-button:hover, .search-trigger:hover { border-color: var(--line-strong); color: var(--ink); } +.mobile-only { display: none; } + +.reading-grid { + display: grid; + grid-template-columns: minmax(0, var(--measure)) var(--outline); + gap: 64px; + justify-content: center; + padding: 68px 44px calc(110px + var(--chapter-dock-reserve)); +} +.chapter { min-width: 0; } +.chapter-head { margin-bottom: 44px; } +.chapter-kicker { display: flex; gap: 11px; align-items: center; margin-bottom: 15px; color: var(--signal-deep); font: 700 11px/1 var(--font-ui); letter-spacing: .14em; text-transform: uppercase; } +.verification { padding: 4px 7px; border: 1px solid currentColor; border-radius: 999px; color: var(--ink-faint); font-size: 9px; letter-spacing: .08em; } +.verification.is-verified { color: var(--green); } +.verification.is-source-checked { color: var(--blue); } +.chapter h1 { + max-width: 16ch; + margin: 0; + font: 760 clamp(38px, 5vw, 64px)/.98 var(--font-display); + letter-spacing: -.055em; + text-wrap: balance; +} +.chapter-summary { + max-width: 700px; + margin: 23px 0 0; + color: var(--ink-soft); + font-size: clamp(20px, 2.1vw, 25px); + line-height: 1.46; +} +.objectives { margin-top: 28px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); } +.objectives summary { padding: 11px 0; color: var(--ink-soft); cursor: pointer; font: 700 12px/1.4 var(--font-ui); } +.objectives ul { margin: 0 0 17px; padding-left: 22px; color: var(--ink-soft); font-size: 16px; } + +.chapter-body h2 { + position: relative; + margin: 64px 0 18px; + font: 740 clamp(27px, 3.2vw, 36px)/1.08 var(--font-display); + letter-spacing: -.035em; + text-wrap: balance; +} +.chapter-body h3 { position: relative; margin: 37px 0 12px; font: 730 21px/1.2 var(--font-display); letter-spacing: -.02em; } +.chapter-body p { margin: 0 0 21px; } +.chapter-body > p:first-child { font-size: 21px; line-height: 1.58; } +.chapter-body strong { font-weight: 700; } +.chapter-body a { color: var(--signal-deep); } +.chapter-body ul, .chapter-body ol { margin: 0 0 24px; padding-left: 25px; } +.chapter-body li { margin: 6px 0; padding-left: 3px; } +.chapter-body > table { + display: block; + width: 100%; + max-width: 100%; + margin: 0 0 28px; + overflow-x: auto; + border-collapse: collapse; + font: 500 14px/1.45 var(--font-ui); + scrollbar-width: thin; +} +.chapter-body > table th, +.chapter-body > table td { padding: 9px 10px; border: 1px solid var(--line); text-align: left; vertical-align: top; } +.chapter-body > table thead th { background: var(--paper-muted); color: var(--ink); font-weight: 750; } +.chapter-body > table tbody th { color: var(--ink); font-weight: 700; } +.chapter-body blockquote { margin: 32px 0; padding: 3px 0 3px 22px; border-left: 4px solid var(--signal); color: var(--ink-soft); font-size: 21px; font-style: italic; } +.chapter-body :not(pre) > code { padding: .14em .34em; border: 1px solid var(--line); border-radius: 4px; background: var(--paper-muted); color: var(--ink); } +.chapter-body hr { margin: 55px 0; border: 0; border-top: 1px solid var(--line); } +.heading-anchor { position: absolute; right: 100%; padding-right: 10px; color: var(--ink-faint) !important; opacity: 0; font: 500 17px/1 var(--font-ui); text-decoration: none; } +.anchored-heading:hover .heading-anchor, .heading-anchor:focus { opacity: 1; } + +.page-outline { position: sticky; top: 90px; align-self: start; max-height: calc(100vh - 115px); overflow: auto; padding-top: 4px; font-family: var(--font-ui); } +.page-outline > strong { color: var(--ink); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; } +.page-outline nav { display: flex; flex-direction: column; gap: 9px; margin-top: 14px; } +.page-outline nav a { border-left: 1px solid var(--line); padding-left: 12px; color: var(--ink-faint); font-size: 11px; line-height: 1.35; text-decoration: none; } +.page-outline nav a:hover { border-left-color: var(--signal); color: var(--ink); } +.page-outline nav a.nested { padding-left: 23px; } +.outline-source { display: block; margin-top: 24px; color: var(--signal-deep); font-size: 10px; font-weight: 700; text-decoration: none; } + +.chapter-footer { margin-top: 82px; padding-top: 28px; border-top: 1px solid var(--line); } +.evidence-stamp { display: flex; gap: 12px; align-items: center; color: var(--ink-faint); font-family: var(--font-ui); } +.stamp-mark { display: grid; width: 36px; height: 36px; place-items: center; border-radius: 9px; background: var(--signal); color: #fff; font-size: 12px; font-weight: 800; } +.evidence-stamp div { display: flex; flex-direction: column; gap: 2px; } +.evidence-stamp strong { color: var(--ink-soft); font-size: 11px; } +.evidence-stamp span { font-size: 10px; } +.chapter-dock { + position: fixed; + z-index: 65; + right: 0; + bottom: 0; + left: var(--sidebar); + padding: 10px 28px calc(10px + env(safe-area-inset-bottom)); + pointer-events: none; + transition: left var(--motion-fast) var(--motion-ease); +} +.chapter-dock-inner { + display: grid; + grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); + gap: 12px; + align-items: center; + width: min(100%, calc(var(--measure) + var(--outline) + 64px)); + min-height: 74px; + margin: 0 auto; + padding: 8px; + border: 1px solid color-mix(in srgb, var(--line-strong) 80%, transparent); + border-radius: 13px; + background: color-mix(in srgb, var(--paper-raised) 92%, transparent); + box-shadow: 0 12px 38px rgb(20 18 14 / 15%); + backdrop-filter: blur(14px); + pointer-events: auto; +} +.chapter-dock-link { + display: flex; + gap: 10px; + align-items: center; + min-width: 0; + min-height: 56px; + padding: 8px 10px; + border: 1px solid transparent; + border-radius: 9px; + color: var(--ink); + text-decoration: none; +} +.chapter-dock-link:hover { border-color: var(--line-strong); background: var(--paper-muted); } +.chapter-dock-link > span[aria-hidden="true"] { flex: none; color: var(--signal-deep); font: 700 18px/1 var(--font-ui); } +.chapter-dock-link-copy { min-width: 0; } +.chapter-dock-link-copy small { display: block; margin-bottom: 4px; color: var(--ink-faint); font: 700 9px/1 var(--font-ui); letter-spacing: .1em; text-transform: uppercase; } +.chapter-dock-link-copy strong { display: block; overflow: hidden; color: var(--ink); font: 700 12px/1.3 var(--font-ui); text-overflow: ellipsis; white-space: nowrap; } +.chapter-dock-link.next { justify-content: flex-end; text-align: right; } +.chapter-dock-context { display: grid; gap: 4px; min-width: 102px; padding: 0 12px; border-right: 1px solid var(--line); border-left: 1px solid var(--line); color: var(--ink-faint); font-family: var(--font-ui); text-align: center; } +.chapter-dock-context > span { max-width: 16ch; overflow: hidden; font-size: 9px; font-weight: 650; letter-spacing: .07em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; } +.chapter-dock-context strong { color: var(--ink-soft); font: 650 11px/1 var(--font-mono); } +.chapter-dock-context b { color: var(--signal-deep); font-weight: 800; } +.chapter-dock-spacer { min-height: 56px; } + +.search-dialog { width: min(720px, calc(100vw - 30px)); max-height: min(780px, calc(100vh - 30px)); padding: 0; border: 1px solid var(--line-strong); border-radius: 16px; background: var(--paper-raised); color: var(--ink); box-shadow: var(--shadow); } +.search-dialog::backdrop { background: rgb(7 10 15 / 56%); backdrop-filter: blur(3px); } +.search-head { display: flex; gap: 20px; align-items: start; justify-content: space-between; padding: 23px 24px 15px; } +.search-eyebrow { color: var(--signal-deep); font: 700 9px/1 var(--font-ui); letter-spacing: .15em; text-transform: uppercase; } +.search-head h2 { margin: 7px 0 0; font: 750 21px/1.15 var(--font-display); letter-spacing: -.025em; } +.search-field { display: flex; gap: 9px; align-items: center; margin: 0 24px; padding: 12px 14px; border: 1px solid var(--line-strong); border-radius: 10px; background: var(--paper); } +.search-field input { width: 100%; border: 0; outline: 0; background: transparent; color: var(--ink); font: 500 15px/1.3 var(--font-ui); } +.search-status { margin: 11px 25px; color: var(--ink-faint); font: 500 11px/1.4 var(--font-ui); } +.search-results { max-height: 520px; overflow-y: auto; padding: 0 14px 16px; } +.search-result { display: block; padding: 13px 11px; border-top: 1px solid var(--line); color: inherit; text-decoration: none; } +.search-result:hover { background: var(--paper-muted); } +.search-result > span { color: var(--signal-deep); font: 700 9px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; } +.search-result strong { display: block; margin-top: 5px; font: 730 15px/1.25 var(--font-ui); } +.search-result p { margin: 5px 0 0; color: var(--ink-soft); font: 400 12px/1.45 var(--font-ui); } +.search-result mark { background: var(--signal-soft); color: inherit; } + +.not-found { width: min(720px, calc(100% - 40px)); margin: 12vh auto; } +.not-found .eyebrow { color: var(--signal-deep); font: 700 11px/1 var(--font-ui); letter-spacing: .15em; text-transform: uppercase; } +.not-found h1 { max-width: 14ch; margin: 15px 0; font: 760 clamp(40px, 8vw, 72px)/.98 var(--font-display); letter-spacing: -.05em; } +.button { display: inline-flex; padding: 11px 16px; border: 1px solid var(--line-strong); border-radius: 8px; font: 700 12px/1 var(--font-ui); text-decoration: none; } +.button.primary { border-color: var(--signal); background: var(--signal); color: #fff; } + +@media (max-width: 1220px) { + .reading-grid { grid-template-columns: minmax(0, var(--measure)); } + .page-outline { display: none; } +} + +@media (min-width: 901px) { + :root[data-sidebar="collapsed"] .sidebar-head { padding: 12px; } + :root[data-sidebar="collapsed"] .sidebar-head-row { flex-direction: column; gap: 9px; align-items: center; } + :root[data-sidebar="collapsed"] .sidebar-toggle { order: -1; } + :root[data-sidebar="collapsed"] .imprint, + :root[data-sidebar="collapsed"] .source-lock { display: none; } + :root[data-sidebar="collapsed"] .book-title { + display: grid; + width: 44px; + height: 44px; + margin: 0; + place-items: center; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--paper-muted); + font-size: 0; + } + :root[data-sidebar="collapsed"] .book-title-mark { display: block; width: 34px; height: 34px; } + :root[data-sidebar="collapsed"] .book-title-copy { display: none; } + :root[data-sidebar="collapsed"] .book-toc { padding: 12px 10px 30px; } + :root[data-sidebar="collapsed"] .toc-part h2 { display: none; } + :root[data-sidebar="collapsed"] .toc-link { grid-template-columns: 1fr; justify-items: center; min-height: 44px; margin: 5px 0; padding: 6px; border-left-width: 2px; } + :root[data-sidebar="collapsed"] .toc-marker { flex-direction: column; gap: 2px; align-items: center; line-height: 1; } + :root[data-sidebar="collapsed"] .toc-icon { font-size: 8px; } + :root[data-sidebar="collapsed"] .toc-number { font-size: 10px; } + :root[data-sidebar="collapsed"] .toc-title { display: none; } + :root[data-sidebar="collapsed"] .sidebar-foot { padding: 14px 10px 18px; text-align: center; } + :root[data-sidebar="collapsed"] .sidebar-foot a { font-size: 0; } + :root[data-sidebar="collapsed"] .sidebar-foot a::before { color: var(--signal-deep); content: "↗"; font: 700 17px/1 var(--font-ui); } +} + +@media (max-width: 900px) { + :root { --chapter-dock-reserve: 102px; } + :root[data-sidebar="collapsed"] { --sidebar: var(--sidebar-expanded); } + .book-sidebar { visibility: hidden; transform: translateX(-102%); transition: transform .2s ease, visibility .2s; box-shadow: var(--shadow); } + .book-sidebar.open { visibility: visible; transform: none; } + .sidebar-toggle { display: none; } + .sidebar-scrim { position: fixed; inset: 0; z-index: 70; display: block; visibility: hidden; background: rgb(7 10 15 / 58%); opacity: 0; transition: opacity .2s ease, visibility .2s; } + .sidebar-scrim.open { visibility: visible; opacity: 1; } + .book-main { margin-left: 0; } + .mobile-only { display: inline-grid; place-items: center; } + .reading-grid { padding: 54px 28px calc(85px + var(--chapter-dock-reserve)); } + .chapter-dock { left: 0; padding-right: 18px; padding-left: 18px; } +} + +@media (max-width: 560px) { + :root { --chapter-dock-reserve: 78px; } + body { font-size: 17px; } + .book-toolbar { padding: 9px 13px; } + .toolbar-crumb span, .search-trigger span:not(:first-child), .search-trigger kbd { display: none; } + .search-trigger { width: 38px; justify-content: center; padding: 0; font-size: 18px; } + .reading-grid { padding: 42px 19px calc(72px + var(--chapter-dock-reserve)); } + .chapter h1 { font-size: 39px; } + .chapter-summary { font-size: 19px; } + .chapter-body h2 { margin-top: 50px; font-size: 28px; } + .chapter-dock { padding: 7px 8px calc(7px + env(safe-area-inset-bottom)); } + .chapter-dock-inner { gap: 3px; min-height: 54px; padding: 4px; border-radius: 10px; } + .chapter-dock-link { gap: 5px; min-height: 44px; padding: 6px; } + .chapter-dock-link-copy small { margin: 0; font-size: 8px; } + .chapter-dock-link-copy strong { display: none; } + .chapter-dock-context { min-width: 46px; padding: 0 7px; } + .chapter-dock-context > span { display: none; } + .chapter-dock-spacer { min-height: 44px; } + .heading-anchor { display: none; } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; } +} + +@media print { + :root { --paper: #fff; --paper-raised: #fff; --paper-muted: #f4f4f4; --ink: #000; --ink-soft: #222; --ink-faint: #444; --line: #bbb; --navy: #fff; --navy-raised: #fff; --navy-line: #777; --navy-text: #000; --navy-muted: #333; } + .book-sidebar, .book-toolbar, .page-outline, .reading-progress, .chapter-dock, .sidebar-tooltip, .search-dialog { display: none !important; } + .book-main { margin: 0; } + .reading-grid { display: block; padding: 0; } + .chapter { max-width: none; } + .chapter-head { break-after: avoid; } + .chapter-body > table { display: table; width: 100%; max-width: none; overflow: visible; table-layout: fixed; font-size: 8pt; } + .chapter-body > table th, .chapter-body > table td { overflow-wrap: anywhere; } + a { color: #000 !important; text-decoration: none; } + .chapter-body p > a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b5b5783 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "astro/tsconfigs/strict", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "resolveJsonModule": true + } +} +