diff --git a/package.json b/package.json index 3fbd08712..bcd532756 100644 --- a/package.json +++ b/package.json @@ -72,11 +72,12 @@ "validate:docs-page": "node scripts/validate-docs-page-assets.cjs", "validate:documentation": "node scripts/validate-documentation-contract.cjs", "validate:workflows": "node scripts/validate-workflow-contract.cjs", - "generate:specifications": "node scripts/validate-specification-catalog.cjs --write && node scripts/validate-github-communication-test-budget.cjs", - "validate:specifications": "node scripts/validate-specification-catalog.cjs && node scripts/validate-github-communication-test-budget.cjs", + "generate:specifications": "node scripts/validate-specification-catalog.cjs --write && node scripts/validate-github-communication-test-budget.cjs && pnpm run validate:browser-extension-specifications", + "validate:specifications": "node scripts/validate-specification-catalog.cjs && node scripts/validate-github-communication-test-budget.cjs && pnpm run validate:browser-extension-specifications", "validate:setup-acceptance": "node scripts/validate-setup-assistant-acceptance.cjs", "lint:fix": "eslint src --fix", - "postinstall": "node scripts/install-git-hooks.cjs" + "postinstall": "node scripts/install-git-hooks.cjs", + "validate:browser-extension-specifications": "node --test test-support/browser-extension-specifications.test.cjs && node scripts/validate-browser-extension-specifications.cjs" }, "keywords": [], "author": "Efra Espada", @@ -98,6 +99,7 @@ "@types/jest": "^30.0.0", "@types/node": "^22.9.1", "@vercel/ncc": "^0.36.1", + "ajv": "6.15.0", "eslint": "^10.10.0", "jest": "^30.5.1", "svelte": "^5.57.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1c41fcdbe..95b2ac16c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@vercel/ncc': specifier: ^0.36.1 version: 0.36.1 + ajv: + specifier: 6.15.0 + version: 6.15.0 eslint: specifier: ^10.10.0 version: 10.10.0 diff --git a/scripts/validate-browser-extension-specifications.cjs b/scripts/validate-browser-extension-specifications.cjs new file mode 100644 index 000000000..a91339ecd --- /dev/null +++ b/scripts/validate-browser-extension-specifications.cjs @@ -0,0 +1,155 @@ +#!/usr/bin/env node + +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const Ajv = require('ajv'); + +const ROOT = path.resolve(__dirname, '..'); +const DATA = 'specs/browser-extension'; +const MODES = { local: 3, settings: 4, read: 4, draft: 5, write: 7, setup: 7, monitor: 7 }; +const WRITE_ACTOR = new Set(['fix', 'dismiss', 'implement', 'remember', 'sync-branch']); +const BRANCH = new Set(['fix', 'implement', 'remember', 'sync-branch']); +const NO_AGENT = new Set(['help', 'status', 'sdd-diff', 'doctor', 'history', 'dismiss', 'remember']); +const DOCUMENTS = [ + 'github-browser-extension.md', 'github-browser-extension-action-integration.md', + 'github-browser-extension-platforms-and-delivery.md', + 'github-browser-extension-functional-catalog.md', + 'github-browser-extension-control-center-and-setup.md', +]; + +function readJson(root, filename) { + return JSON.parse(fs.readFileSync(path.join(root, DATA, filename), 'utf8')); +} + +function compiler(root, filename) { + const ajv = new Ajv({ allErrors: true, strictKeywords: true, strictDefaults: true }); + return ajv.compile(readJson(root, filename)); +} + +function requireSchema(validate, value, name) { + assert(validate(value), `${name} violates its JSON schema: ${JSON.stringify(validate.errors)}`); +} + +function unique(values, name) { + assert.equal(new Set(values).size, values.length, `${name} must be unique`); +} + +function loadFeatureCatalog(root = ROOT, index = readJson(root, 'feature-catalog.v1.json')) { + requireSchema(compiler(root, 'feature-catalog-index.schema.json'), index, 'feature index'); + unique(index.families.map(family => family.id), 'indexed family IDs'); + const families = index.families.map(reference => { + assert.equal(reference.file, `features/${reference.id}.v1.json`, `${reference.id} family path mismatch`); + assert(fs.statSync(path.join(root, DATA, reference.file)).size <= 96 * 1024, `${reference.id} family exceeds reviewable file budget`); + const family = readJson(root, reference.file); + assert.equal(family.id, reference.id, `${reference.id} indexed family identity mismatch`); + assert.equal(family.title, reference.title, `${reference.id} indexed family title mismatch`); + return family; + }); + return { ...index, $schema: './feature-catalog.schema.json', families }; +} + +function validateFeatures(catalog, schema) { + requireSchema(schema, catalog, 'feature catalog'); + unique(catalog.families.map(family => family.id), 'family IDs'); + const features = catalog.families.flatMap(family => { + for (const feature of family.features) { + assert.equal(feature.family, family.id, `${feature.id} family mismatch`); + assert(feature.id.startsWith(`BEX-${family.id}-`), `${feature.id} ID namespace mismatch`); + assert.deepEqual(feature.requirements, [`CAT-${family.id}`], `${feature.id} requirement mismatch`); + assert.equal(feature.tests.length, MODES[feature.mode], `${feature.id} risk-case allocation mismatch`); + for (const item of feature.tests) { + assert(item.id.startsWith(`bexp-${family.id}${feature.id.slice(-2)}-C`), `${item.id} case namespace mismatch`); + } + } + return family.features; + }); + unique(features.map(feature => feature.id), 'feature IDs'); + const cases = features.flatMap(feature => feature.tests); + unique(cases.map(item => item.id), 'feature case IDs'); + unique(cases.map(item => item.scenario), 'feature scenarios'); + assert.equal(features.length, 150, 'The full product requires its 150 registered capabilities'); + assert.equal(cases.length, 659, 'Feature risk inventory must contain 659 distinct cases'); + return { features, featureCases: cases.length }; +} + +function validateFeatureTraceability(catalog, text) { + const section = text.split(/^## 17\. Requirements traceability$/m)[1]?.split(/^## 18\. /m)[0]; + assert(section, 'Feature requirements traceability section missing'); + const rows = section.split('\n').filter(line => line.includes('|')) + .map(line => line.trim().replace(/^\||\|$/g, '').split('|').map(cell => cell.trim())) + .filter(cells => /^CAT-/i.test(cells[0])); + for (const family of catalog.families) { + const matches = rows.filter(cells => cells[0] === `CAT-${family.id}`); + assert.equal(matches.length, 1, `CAT-${family.id} must have exactly one traceability row`); + const cells = matches[0]; + assert.equal(cells[1], family.features.map(feature => feature.id).join(', '), `CAT-${family.id} feature traceability mismatch`); + const count = family.features.reduce((total, feature) => total + feature.tests.length, 0); + assert.equal(cells[2], `${count} explicit cases in the JSON test inventory`, `CAT-${family.id} case traceability mismatch`); + } + assert.equal(rows.length, catalog.families.length, 'Unregistered feature traceability rows'); +} + +function validateRequests(descriptor, schema, knownNames) { + requireSchema(schema, descriptor, 'request catalog'); + unique(descriptor.commands.map(command => command.name), 'command names'); + assert.deepEqual(descriptor.commands.map(command => command.name).sort(), [...knownNames].sort(), 'Command catalog must match the documented contract'); + for (const command of descriptor.commands) { + assert.equal(command.requiresWriteActor, WRITE_ACTOR.has(command.name), `${command.name} write-actor guard mismatch`); + assert.equal(command.requiresVerifiedBranch, BRANCH.has(command.name), `${command.name} branch guard mismatch`); + const effect = BRANCH.has(command.name) ? 'files' : command.name === 'dismiss' ? 'finding-state' + : command.name === 'description' ? 'pr-description' : 'publication'; + assert.equal(command.effect, effect, `${command.name} effect classification mismatch`); + const agent = NO_AGENT.has(command.name) ? 'never' : command.name === 'sync-branch' ? 'conditional' : 'may-run'; + assert.equal(command.agent, agent, `${command.name} agent classification mismatch`); + if (['fix', 'implement'].includes(command.name)) { + assert.deepEqual(command.contexts, ['review-thread'], `${command.name} cannot broaden the example's authoritative route`); + } + } +} + +function validate(root = ROOT) { + const catalog = loadFeatureCatalog(root); + const result = validateFeatures(catalog, compiler(root, 'feature-catalog.schema.json')); + const commandReference = fs.readFileSync(path.join(root, 'docs/issues/comment-commands.mdx'), 'utf8'); + const names = [...commandReference.matchAll(/^\| `\/copilot ([a-z-]+)/gm)].map(match => match[1]); + unique(names, 'documented command names'); + validateRequests(readJson(root, 'examples/requests-v2.json'), compiler(root, 'requests-v2.schema.json'), names); + const manifest = compiler(root, 'manifest-v1.schema.json'); + const status = compiler(root, 'status-v1.schema.json'); + requireSchema(manifest, readJson(root, 'examples/manifest-v1.json'), 'manifest fixture'); + for (const filename of ['status-pr-v1.json', 'status-issue-v1.json']) { + requireSchema(status, readJson(root, `examples/${filename}`), filename); + } + assert.equal(status(readJson(root, 'examples/status-invalid-head-v1.json')), false, 'Invalid-head negative fixture must reject'); + const texts = new Map(DOCUMENTS.map(name => [name, fs.readFileSync(path.join(root, 'specs', name), 'utf8')])); + for (const [name, text] of texts) { + assert(!/\bMVP\b/i.test(text), `${name} must express the complete product contract`); + for (let section = 1; section <= 20; section++) { + assert.equal([...text.matchAll(new RegExp(`^## ${section}\\. `, 'gm'))].length, 1, `${name} must have one section ${section}`); + } + assert(/\b803\b/.test(text), `${name} must agree on the complete 803-case budget`); + } + const primary = texts.get(DOCUMENTS[0]); + const core = [...primary.matchAll(/^\| (bex-[A-Z]-C\d+) \|/gm)].map(match => match[1]); + const center = [...texts.get(DOCUMENTS[4]).matchAll(/^\| (bexhub-[A-Z]+-C\d+) \|/gm)].map(match => match[1]); + unique([...core, ...center], 'cross-cutting case IDs'); + assert.equal(core.length, 96, 'Retain all 96 core cases'); + assert.equal(center.length, 48, 'Retain all 48 center/setup integration cases'); + assert.equal(core.length + center.length + result.featureCases, 803); + assert(primary.includes('| specs/github-browser-extension.md | create |'), 'PR publication inventory must classify the new primary as create'); + const catalogText = texts.get(DOCUMENTS[3]); + validateFeatureTraceability(catalog, catalogText); + for (const feature of result.features) assert(catalogText.includes(`| ${feature.id} — `), `${feature.id} missing from the readable catalog`); + const capability = JSON.parse(fs.readFileSync(path.join(root, 'specs/catalog.json'), 'utf8')).capabilities.find(item => item.id === 'github-browser-extension'); + assert.equal(catalog.runtimeVerified, false, 'Specification inventory must not claim runtime evidence'); + for (const name of DOCUMENTS) assert(capability.specs.includes(`specs/${name}`), `${name} missing from capability ownership`); + return { features: result.features.length, commands: names.length, cases: 803, schemas: 5, positiveFixtures: 6, expectedNegativeFixtures: 1 }; +} + +if (require.main === module) { + try { console.log(`Browser-extension specification contract: PASS ${JSON.stringify(validate())}`); } + catch (error) { console.error(`Browser-extension specification contract: FAIL ${error.message}`); process.exitCode = 1; } +} + +module.exports = { validate, validateFeatures, validateFeatureTraceability, validateRequests, compiler, readJson, loadFeatureCatalog }; diff --git a/specs/CATALOG.md b/specs/CATALOG.md index 43093e6c2..6205fd630 100644 --- a/specs/CATALOG.md +++ b/specs/CATALOG.md @@ -17,7 +17,7 @@ debt or convert unknown historic intent into a design decision. | `execution-lifecycle` | Implemented | Shared GitHub Action lifecycle with pinned native resource/lane coordination proof, conservative predecessor fencing, routing and durable user-facing results | [Execution admission, queueing, routing, and result publication](./execution-admission-queue-and-publication.md) + 3 companion | 119 paths · 2026-10-25 | | `architecture-quality-hardening` | Implemented | Close verified concurrency, error-contract, context-coupling, fan-out, setup/doctor, and provider-policy risks in dependency order | [Architecture quality and scalability hardening](./architecture-quality-and-scalability-hardening.md) + 1 companion | 72 paths · 2026-10-13 | | `setup-and-doctor` | Implemented | Plan, validate, provision, and audit a repository installation without exposing credentials | [Setup, configuration, credentials, and doctor](./setup-configuration-credentials-and-doctor.md) + 6 companion | 332 paths · 2026-10-24 | -| `local-web-setup-assistant` | Proposed | Offer a packaged, loopback-only Svelte setup interface over the existing engine with four-language guidance, English CLI help, basic/custom first-run paths, editable question and plan review, source-labelled GitHub facts, assisted CI and Project evidence, role-separated PATs, and truthful itemized outcomes; inspect existing configuration and apply independent, scope-aware runtime adjustments with permission, drift and read-back verification | [Local web setup assistant](./local-web-setup-assistant.md) + 2 companion | 247 paths · 2026-10-21 | +| `local-web-setup-assistant` | Proposed | Offer a packaged, loopback-only Svelte setup interface over the existing engine with four-language guidance, English CLI help, basic/custom first-run paths, editable question and plan review, source-labelled GitHub facts, assisted CI and Project evidence, role-separated PATs, and truthful itemized outcomes; inspect existing configuration and apply independent, scope-aware runtime adjustments with permission, drift and read-back verification | [Local web setup assistant](./local-web-setup-assistant.md) + 2 companion | 248 paths · 2026-10-21 | | `guided-bot-pat-onboarding` | Proposed | Guide creation of the persistent workflow PAT, verify bot identity and grants, recover explicitly from wrong-account input within the session, and install the approved Actions Secret | [Guided bot PAT onboarding](./guided-bot-pat-onboarding.md) | 39 paths · 2026-10-07 | | `temporary-setup-operator-authorization` | Proposed | Guide creation of the one-run operator PAT through GitHub's official form, verify final setup access, and report user-owned deletion accurately | [Assisted setup PAT creation](./temporary-setup-operator-authorization.md) | 36 paths · 2026-10-18 | | `issue-start-and-sdd-readiness` | Implemented | Start every admitted issue with one explicit signal and publish a validated SDD before eligible Action-managed branch work; inspect verified SDD status and bounded structural publication comparisons | [Uniform issue start and pre-branch SDD readiness](./issue-start-and-branch-readiness.md) + 3 companion | 120 paths · 2026-10-25 | @@ -31,6 +31,7 @@ debt or convert unknown historic intent into a design decision. | `configurable-issue-workflows` | Implemented | Select one canonical set of issue workflows and enforce its forms, dependencies, branch policy, runtime admission, migration, and diagnosis | [Configurable issue workflows and fail-closed admission](./configurable-issue-workflows-and-admission.md) | 89 paths · 2026-10-13 | | `repository-agent-collaboration` | Implemented | Generate safe repository-local profiles, guidance, and a skill for agents contributing through configured issues, Action-managed branches, pull requests, and deployment boundaries | [Repository agent collaboration contract](./repository-agent-collaboration-contract.md) | 47 paths · 2026-10-17 | | `guarded-pull-request-approval` | Proposed | Specify and locally implement revision-bound, evidence-gated native bot approvals for eligible human pull requests, with safe setup defaults, read-only doctor checks, and explainable recovery | [Guarded pull-request approval and setup readiness](./guarded-pull-request-approval.md) + 2 companion | 94 paths · 2026-10-22 | +| `github-browser-extension` | Proposed | Complete proposed desktop product: 150 required functions, packaged local center, full compatible Action integration, shared setup and 803 distinct future acceptance cases; runtime remains unimplemented | [Complete GitHub productivity extension and integrated Copilot setup](./github-browser-extension.md) + 4 companion | 29 paths · 2026-10-25 | ## Evidence map @@ -120,7 +121,7 @@ debt or convert unknown historic intent into a design decision. - Entrypoints: [`src/cli/commands/setup.ts`](../src/cli/commands/setup.ts) · [`package.json`](../package.json) · [`web/src/main.ts`](../web/src/main.ts) - Core code: [`web/src/App.svelte`](../web/src/App.svelte) · [`web/src/session/setupSession.ts`](../web/src/session/setupSession.ts) · [`web/src/components/ActionButton.svelte`](../web/src/components/ActionButton.svelte) · [`web/src/components/PairingPanel.svelte`](../web/src/components/PairingPanel.svelte) · [`web/src/lib/pairingCode.ts`](../web/src/lib/pairingCode.ts) · [`web/src/components/ContextPanel.svelte`](../web/src/components/ContextPanel.svelte) · [`web/src/i18n/permissionEvidence.ts`](../web/src/i18n/permissionEvidence.ts) · [`web/src/i18n/permissionProgress.ts`](../web/src/i18n/permissionProgress.ts) · [`web/src/components/PermissionProgressPanel.svelte`](../web/src/components/PermissionProgressPanel.svelte) · [`web/src/components/PromptCard.svelte`](../web/src/components/PromptCard.svelte) · [`web/src/components/ResultPanel.svelte`](../web/src/components/ResultPanel.svelte) · [`web/src/components/SetupPatCorrectionPanel.svelte`](../web/src/components/SetupPatCorrectionPanel.svelte) · [`web/src/components/ResourceProgress.svelte`](../web/src/components/ResourceProgress.svelte) · [`web/src/components/PlanPrompt.svelte`](../web/src/components/PlanPrompt.svelte) · [`web/src/components/PlanDecisionSummary.svelte`](../web/src/components/PlanDecisionSummary.svelte) · [`web/src/components/QuestionPrompt.svelte`](../web/src/components/QuestionPrompt.svelte) · [`web/src/components/FixedWorkflowNotice.svelte`](../web/src/components/FixedWorkflowNotice.svelte) · [`web/src/components/QuestionGuidance.svelte`](../web/src/components/QuestionGuidance.svelte) · [`web/src/components/DiscoveryNotice.svelte`](../web/src/components/DiscoveryNotice.svelte) · [`web/src/components/ProducerSelector.svelte`](../web/src/components/ProducerSelector.svelte) · [`web/src/lib/manualProducerIdentity.ts`](../web/src/lib/manualProducerIdentity.ts) · [`web/src/components/CoverageCheckEvidence.svelte`](../web/src/components/CoverageCheckEvidence.svelte) · [`web/src/components/ProjectSelector.svelte`](../web/src/components/ProjectSelector.svelte) · [`web/src/i18n/catalog.ts`](../web/src/i18n/catalog.ts) · [`web/src/i18n/projectTransitions.ts`](../web/src/i18n/projectTransitions.ts) · [`web/src/i18n/permissionTerms.ts`](../web/src/i18n/permissionTerms.ts) · [`web/src/components/StatusBanner.svelte`](../web/src/components/StatusBanner.svelte) · [`web/src/lib/questionAnswer.ts`](../web/src/lib/questionAnswer.ts) · [`web/src/lib/githubLink.ts`](../web/src/lib/githubLink.ts) · [`web/src/lib/focusOnRevision.ts`](../web/src/lib/focusOnRevision.ts) · [`web/src/i18n/featureNames.ts`](../web/src/i18n/featureNames.ts) · [`web/src/i18n/agentRoleNames.ts`](../web/src/i18n/agentRoleNames.ts) · [`web/src/i18n/checkEvidence.ts`](../web/src/i18n/checkEvidence.ts) · [`web/src/styles/controls.css`](../web/src/styles/controls.css) · [`web/src/styles/tokens.css`](../web/src/styles/tokens.css) · [`web/src/style.css`](../web/src/style.css) · [`src/application/contracts/web_setup_view.ts`](../src/application/contracts/web_setup_view.ts) · [`src/application/ports/setup_terminal_ports.ts`](../src/application/ports/setup_terminal_ports.ts) · [`src/application/errors/setup_interaction_cancelled_error.ts`](../src/application/errors/setup_interaction_cancelled_error.ts) · [`src/application/policies/merge_setup_overrides_policy.ts`](../src/application/policies/merge_setup_overrides_policy.ts) · [`src/application/policies/setup_remote_facts_policy.ts`](../src/application/policies/setup_remote_facts_policy.ts) · [`src/application/usecases/setup/prepare_setup_pat_intent_use_case.ts`](../src/application/usecases/setup/prepare_setup_pat_intent_use_case.ts) · [`src/application/usecases/setup/audit_configured_setup_pat_use_case.ts`](../src/application/usecases/setup/audit_configured_setup_pat_use_case.ts) · [`src/infrastructure/setup_permission_actions_probe.ts`](../src/infrastructure/setup_permission_actions_probe.ts) · [`src/infrastructure/setup_permission_issue_probe.ts`](../src/infrastructure/setup_permission_issue_probe.ts) · [`src/infrastructure/setup_permission_issue_cleanup.ts`](../src/infrastructure/setup_permission_issue_cleanup.ts) · [`src/infrastructure/setup_permission_probe_journal.ts`](../src/infrastructure/setup_permission_probe_journal.ts) · [`src/infrastructure/setup_permission_probe_transaction.ts`](../src/infrastructure/setup_permission_probe_transaction.ts) · [`src/infrastructure/setup_permission_resource_probes.ts`](../src/infrastructure/setup_permission_resource_probes.ts) · [`src/application/usecases/setup/verify_web_setup_apply_use_case.ts`](../src/application/usecases/setup/verify_web_setup_apply_use_case.ts) · [`src/application/usecases/setup/setup_session_coordinator.ts`](../src/application/usecases/setup/setup_session_coordinator.ts) · [`src/application/usecases/setup/verify_setup_pat_bootstrap_use_case.ts`](../src/application/usecases/setup/verify_setup_pat_bootstrap_use_case.ts) · [`src/cli_context.ts`](../src/cli_context.ts) · [`src/cli/setup_command_options.ts`](../src/cli/setup_command_options.ts) · [`src/cli/commands/setup_execution.ts`](../src/cli/commands/setup_execution.ts) · [`src/cli/setup_credential_collection.ts`](../src/cli/setup_credential_collection.ts) · [`src/cli/setup_pat_intent_adapter.ts`](../src/cli/setup_pat_intent_adapter.ts) · [`src/cli/setup_apply_authorization.ts`](../src/cli/setup_apply_authorization.ts) · [`src/cli/setup_outcome_adapter.ts`](../src/cli/setup_outcome_adapter.ts) · [`src/cli/web_setup_bridge.ts`](../src/cli/web_setup_bridge.ts) · [`src/cli/web_setup_adapters.ts`](../src/cli/web_setup_adapters.ts) · [`src/cli/web_setup_server.ts`](../src/cli/web_setup_server.ts) · [`src/cli/setup_apply_snapshot.ts`](../src/cli/setup_apply_snapshot.ts) · [`src/cli/setup_result_receipt.ts`](../src/cli/setup_result_receipt.ts) · [`src/application/usecases/actions/initial_setup_workflow.ts`](../src/application/usecases/actions/initial_setup_workflow.ts) · [`src/actions/local_action.ts`](../src/actions/local_action.ts) · [`src/cli/setup_session_guard.ts`](../src/cli/setup_session_guard.ts) · [`src/application/usecases/setup/setup_wizard_use_case.ts`](../src/application/usecases/setup/setup_wizard_use_case.ts) · [`src/application/usecases/setup/setup_questionnaire_controller.ts`](../src/application/usecases/setup/setup_questionnaire_controller.ts) · [`src/application/policies/setup_terminal_choice_policy.ts`](../src/application/policies/setup_terminal_choice_policy.ts) · [`src/cli/setup_terminal_driver.ts`](../src/cli/setup_terminal_driver.ts) · [`src/cli/setup_question_renderer.ts`](../src/cli/setup_question_renderer.ts) · [`src/application/usecases/setup/setup_journey_use_case.ts`](../src/application/usecases/setup/setup_journey_use_case.ts) · [`src/application/usecases/setup/setup_credentials_use_case.ts`](../src/application/usecases/setup/setup_credentials_use_case.ts) · [`src/application/policies/setup_questionnaire_policy.ts`](../src/application/policies/setup_questionnaire_policy.ts) · [`src/application/policies/setup_project_selection_policy.ts`](../src/application/policies/setup_project_selection_policy.ts) · [`src/application/ports/setup_project_discovery_port.ts`](../src/application/ports/setup_project_discovery_port.ts) · [`src/application/ports/setup_approval_check_discovery_port.ts`](../src/application/ports/setup_approval_check_discovery_port.ts) · [`src/infrastructure/github_setup_project_discovery_adapter.ts`](../src/infrastructure/github_setup_project_discovery_adapter.ts) · [`src/infrastructure/github_setup_approval_check_discovery_adapter.ts`](../src/infrastructure/github_setup_approval_check_discovery_adapter.ts) · [`src/application/policies/setup_question_documentation_policy.ts`](../src/application/policies/setup_question_documentation_policy.ts) · [`src/application/policies/setup_question_guidance_policy.ts`](../src/application/policies/setup_question_guidance_policy.ts) · [`src/application/policies/setup_question_purpose_policy.ts`](../src/application/policies/setup_question_purpose_policy.ts) · [`src/application/policies/setup_token_permission_policy.ts`](../src/application/policies/setup_token_permission_policy.ts) · [`src/application/policies/setup_configuration_plan.ts`](../src/application/policies/setup_configuration_plan.ts) · [`src/application/policies/setup_pat_creation_url_policy.ts`](../src/application/policies/setup_pat_creation_url_policy.ts) · [`src/infrastructure/composition/setup_credentials_composition_root.ts`](../src/infrastructure/composition/setup_credentials_composition_root.ts) · [`scripts/validate-npm-package.cjs`](../scripts/validate-npm-package.cjs) · [`scripts/smoke-test-npm-package.cjs`](../scripts/smoke-test-npm-package.cjs) · [`scripts/smoke-packaged-web-session.cjs`](../scripts/smoke-packaged-web-session.cjs) · [`scripts/validate-setup-assistant-acceptance.cjs`](../scripts/validate-setup-assistant-acceptance.cjs) · [`scripts/serve-web-setup-review.cjs`](../scripts/serve-web-setup-review.cjs) · [`scripts/validate-workflow-contract.cjs`](../scripts/validate-workflow-contract.cjs) · [`scripts/documentation_checkout_text.cjs`](../scripts/documentation_checkout_text.cjs) · [`scripts/set-cli-executable.cjs`](../scripts/set-cli-executable.cjs) · [`scripts/render-web-setup-component.cjs`](../scripts/render-web-setup-component.cjs) · [`web/src/i18n/permissionPrerequisite.ts`](../web/src/i18n/permissionPrerequisite.ts) · [`scripts/web-setup-review-views.cjs`](../scripts/web-setup-review-views.cjs) · [`src/application/usecases/setup/resolve_setup_workflow_pat_conflict_use_case.ts`](../src/application/usecases/setup/resolve_setup_workflow_pat_conflict_use_case.ts) · [`src/cli/setup_workflow_pat_storage_copy.ts`](../src/cli/setup_workflow_pat_storage_copy.ts) · [`web/src/components/WorkflowPatStorageNotice.svelte`](../web/src/components/WorkflowPatStorageNotice.svelte) · [`src/cli/commands/setup_policy.ts`](../src/cli/commands/setup_policy.ts) · [`src/application/usecases/execution/execution_issue_number_policy.ts`](../src/application/usecases/execution/execution_issue_number_policy.ts) · [`src/application/usecases/execution/setup_execution_workflow.ts`](../src/application/usecases/execution/setup_execution_workflow.ts) · [`src/domain/setup_management.ts`](../src/domain/setup_management.ts) · [`src/application/contracts/setup_management_view.ts`](../src/application/contracts/setup_management_view.ts) · [`src/application/ports/setup_management_ports.ts`](../src/application/ports/setup_management_ports.ts) · [`src/application/policies/setup_quick_settings_policy.ts`](../src/application/policies/setup_quick_settings_policy.ts) · [`src/application/policies/setup_management_policy.ts`](../src/application/policies/setup_management_policy.ts) · [`src/application/policies/setup_management_permissions_policy.ts`](../src/application/policies/setup_management_permissions_policy.ts) · [`src/application/usecases/setup/manage_setup_use_case.ts`](../src/application/usecases/setup/manage_setup_use_case.ts) · [`src/infrastructure/setup_management_workspace_adapter.ts`](../src/infrastructure/setup_management_workspace_adapter.ts) · [`src/cli/setup_management_adapter.ts`](../src/cli/setup_management_adapter.ts) · [`web/src/components/SetupManagementPanel.svelte`](../web/src/components/SetupManagementPanel.svelte) · [`web/src/components/ManagementInventory.svelte`](../web/src/components/ManagementInventory.svelte) · [`web/src/components/QuickSettingPrompt.svelte`](../web/src/components/QuickSettingPrompt.svelte) · [`web/src/i18n/managementCopy.ts`](../web/src/i18n/managementCopy.ts) · [`web/src/styles/management.css`](../web/src/styles/management.css) · [`scripts/coverage-budgets.json`](../scripts/coverage-budgets.json) · [`web/src/session/setupCommandTransport.ts`](../web/src/session/setupCommandTransport.ts) · [`scripts/serve-web-setup-journey.cjs`](../scripts/serve-web-setup-journey.cjs) · [`web/src/components/SetupHeader.svelte`](../web/src/components/SetupHeader.svelte) · [`web/src/components/WaitingPanel.svelte`](../web/src/components/WaitingPanel.svelte) · [`web/src/styles/layout.css`](../web/src/styles/layout.css) · [`web/src/i18n/en.ts`](../web/src/i18n/en.ts) · [`web/src/i18n/es.ts`](../web/src/i18n/es.ts) · [`web/src/i18n/fr.ts`](../web/src/i18n/fr.ts) · [`web/src/i18n/pt.ts`](../web/src/i18n/pt.ts) · [`web/src/i18n/sessionErrors.ts`](../web/src/i18n/sessionErrors.ts) · [`web/src/i18n/errors/en.ts`](../web/src/i18n/errors/en.ts) · [`web/src/i18n/errors/es.ts`](../web/src/i18n/errors/es.ts) · [`web/src/i18n/errors/fr.ts`](../web/src/i18n/errors/fr.ts) · [`web/src/i18n/errors/pt.ts`](../web/src/i18n/errors/pt.ts) · [`web/src/components/SetupSidebar.svelte`](../web/src/components/SetupSidebar.svelte) · [`web/src/components/RepositorySelector.svelte`](../web/src/components/RepositorySelector.svelte) · [`web/src/components/BatchSetupPanel.svelte`](../web/src/components/BatchSetupPanel.svelte) · [`web/src/components/BatchSafetyBanner.svelte`](../web/src/components/BatchSafetyBanner.svelte) · [`web/src/components/InstallationReview.svelte`](../web/src/components/InstallationReview.svelte) · [`web/src/components/RunnerQuestionDetails.svelte`](../web/src/components/RunnerQuestionDetails.svelte) · [`web/src/i18n/runnerCopy.ts`](../web/src/i18n/runnerCopy.ts) · [`scripts/web-setup-runner-review-fixtures.cjs`](../scripts/web-setup-runner-review-fixtures.cjs) · [`src/application/contracts/setup_documentation.ts`](../src/application/contracts/setup_documentation.ts) · [`src/cli/setup_journey_presenter.ts`](../src/cli/setup_journey_presenter.ts) · [`web/src/components/SetupHelp.svelte`](../web/src/components/SetupHelp.svelte) · [`web/src/components/CompletedSetupHelp.svelte`](../web/src/components/CompletedSetupHelp.svelte) · [`src/domain/setup_verification_action.ts`](../src/domain/setup_verification_action.ts) · [`src/infrastructure/setup_verification_action.ts`](../src/infrastructure/setup_verification_action.ts) · [`src/application/policies/setup_verification_action_summary_policy.ts`](../src/application/policies/setup_verification_action_summary_policy.ts) - Tests: [`src/__tests__/cli.test.ts`](../src/__tests__/cli.test.ts) · [`src/__tests__/cli_context_branch.test.ts`](../src/__tests__/cli_context_branch.test.ts) · [`src/__tests__/cli_context_root.test.ts`](../src/__tests__/cli_context_root.test.ts) · [`src/cli/__tests__/web_setup_bridge.test.ts`](../src/cli/__tests__/web_setup_bridge.test.ts) · [`src/cli/__tests__/web_setup_adapters.test.ts`](../src/cli/__tests__/web_setup_adapters.test.ts) · [`src/cli/__tests__/web_setup_palette.test.ts`](../src/cli/__tests__/web_setup_palette.test.ts) · [`src/cli/__tests__/web_setup_ui_helpers.test.ts`](../src/cli/__tests__/web_setup_ui_helpers.test.ts) · [`src/cli/__tests__/web_setup_browser_session.test.ts`](../src/cli/__tests__/web_setup_browser_session.test.ts) · [`src/cli/__tests__/web_setup_server.test.ts`](../src/cli/__tests__/web_setup_server.test.ts) · [`src/cli/__tests__/web_setup_browser_open.test.ts`](../src/cli/__tests__/web_setup_browser_open.test.ts) · [`src/cli/__tests__/setup_apply_snapshot.test.ts`](../src/cli/__tests__/setup_apply_snapshot.test.ts) · [`src/cli/__tests__/setup_result_receipt.test.ts`](../src/cli/__tests__/setup_result_receipt.test.ts) · [`src/cli/__tests__/setup_session_guard.test.ts`](../src/cli/__tests__/setup_session_guard.test.ts) · [`src/cli/__tests__/setup_command_options.test.ts`](../src/cli/__tests__/setup_command_options.test.ts) · [`src/cli/__tests__/web_setup_components.test.ts`](../src/cli/__tests__/web_setup_components.test.ts) · [`src/cli/__tests__/setup_terminal_driver.test.ts`](../src/cli/__tests__/setup_terminal_driver.test.ts) · [`src/cli/__tests__/setup_terminal_driver_stream_integration.test.ts`](../src/cli/__tests__/setup_terminal_driver_stream_integration.test.ts) · [`src/cli/__tests__/setup_presenters.test.ts`](../src/cli/__tests__/setup_presenters.test.ts) · [`src/cli/__tests__/web_setup_catalog.test.ts`](../src/cli/__tests__/web_setup_catalog.test.ts) · [`src/architecture/__tests__/web_setup_boundaries.test.ts`](../src/architecture/__tests__/web_setup_boundaries.test.ts) · [`src/application/usecases/setup/__tests__/prepare_setup_pat_intent_use_case.test.ts`](../src/application/usecases/setup/__tests__/prepare_setup_pat_intent_use_case.test.ts) · [`src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts`](../src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts) · [`src/infrastructure/__tests__/setup_permission_resource_probes.test.ts`](../src/infrastructure/__tests__/setup_permission_resource_probes.test.ts) · [`src/application/usecases/setup/__tests__/verify_web_setup_apply_use_case.test.ts`](../src/application/usecases/setup/__tests__/verify_web_setup_apply_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_session_coordinator.test.ts`](../src/application/usecases/setup/__tests__/setup_session_coordinator.test.ts) · [`src/application/usecases/actions/__tests__/initial_setup_use_case.test.ts`](../src/application/usecases/actions/__tests__/initial_setup_use_case.test.ts) · [`src/actions/__tests__/local_action.test.ts`](../src/actions/__tests__/local_action.test.ts) · [`src/tooling/__tests__/validate_workflow_contract.test.ts`](../src/tooling/__tests__/validate_workflow_contract.test.ts) · [`src/domain/__tests__/setup_approval_workflow.test.ts`](../src/domain/__tests__/setup_approval_workflow.test.ts) · [`src/tooling/__tests__/documentation_checkout_text.test.ts`](../src/tooling/__tests__/documentation_checkout_text.test.ts) · [`src/application/policies/__tests__/setup_remote_facts_policy.test.ts`](../src/application/policies/__tests__/setup_remote_facts_policy.test.ts) · [`src/application/usecases/setup/__tests__/verify_setup_pat_bootstrap_use_case.test.ts`](../src/application/usecases/setup/__tests__/verify_setup_pat_bootstrap_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_questionnaire_controller.test.ts`](../src/application/usecases/setup/__tests__/setup_questionnaire_controller.test.ts) · [`src/application/usecases/setup/__tests__/setup_journey_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_journey_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_credentials_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_credentials_use_case.test.ts) · [`src/application/policies/__tests__/setup_questionnaire_policy.test.ts`](../src/application/policies/__tests__/setup_questionnaire_policy.test.ts) · [`src/application/policies/__tests__/setup_project_selection_policy.test.ts`](../src/application/policies/__tests__/setup_project_selection_policy.test.ts) · [`src/infrastructure/__tests__/github_setup_project_discovery_adapter.test.ts`](../src/infrastructure/__tests__/github_setup_project_discovery_adapter.test.ts) · [`src/infrastructure/__tests__/github_setup_approval_check_discovery_adapter.test.ts`](../src/infrastructure/__tests__/github_setup_approval_check_discovery_adapter.test.ts) · [`src/infrastructure/__tests__/setup_check_discovery_sdk_contract.integration.test.ts`](../src/infrastructure/__tests__/setup_check_discovery_sdk_contract.integration.test.ts) · [`src/application/policies/__tests__/setup_question_documentation_policy.test.ts`](../src/application/policies/__tests__/setup_question_documentation_policy.test.ts) · [`src/application/policies/__tests__/setup_question_purpose_policy.test.ts`](../src/application/policies/__tests__/setup_question_purpose_policy.test.ts) · [`src/application/policies/__tests__/setup_token_permission_policy.test.ts`](../src/application/policies/__tests__/setup_token_permission_policy.test.ts) · [`src/architecture/__tests__/setup_doctor_boundaries.test.ts`](../src/architecture/__tests__/setup_doctor_boundaries.test.ts) · [`src/infrastructure/__tests__/setup_pat_audit.test.ts`](../src/infrastructure/__tests__/setup_pat_audit.test.ts) · [`src/infrastructure/__tests__/setup_permission_projects_access.test.ts`](../src/infrastructure/__tests__/setup_permission_projects_access.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_recovery.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_recovery.test.ts) · [`src/cli/__tests__/web_setup_bot_pat_recovery.test.ts`](../src/cli/__tests__/web_setup_bot_pat_recovery.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_conflict.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_conflict.test.ts) · [`src/application/usecases/setup/__tests__/setup_workflow_pat_credential_rotation.test.ts`](../src/application/usecases/setup/__tests__/setup_workflow_pat_credential_rotation.test.ts) · [`src/data/repository/__tests__/setup_organization_pat_inventory.test.ts`](../src/data/repository/__tests__/setup_organization_pat_inventory.test.ts) · [`src/cli/__tests__/web_setup_bot_pat_scope_conflict.test.ts`](../src/cli/__tests__/web_setup_bot_pat_scope_conflict.test.ts) · [`src/actions/__tests__/local_setup_apply_contract.test.ts`](../src/actions/__tests__/local_setup_apply_contract.test.ts) · [`src/cli/commands/__tests__/setup_policy.test.ts`](../src/cli/commands/__tests__/setup_policy.test.ts) · [`src/application/usecases/execution/__tests__/execution_issue_number_policy.test.ts`](../src/application/usecases/execution/__tests__/execution_issue_number_policy.test.ts) · [`src/application/usecases/execution/__tests__/setup_execution_workflow.test.ts`](../src/application/usecases/execution/__tests__/setup_execution_workflow.test.ts) · [`src/application/policies/__tests__/setup_management_policy.test.ts`](../src/application/policies/__tests__/setup_management_policy.test.ts) · [`src/application/usecases/setup/__tests__/manage_setup_use_case.test.ts`](../src/application/usecases/setup/__tests__/manage_setup_use_case.test.ts) · [`src/infrastructure/__tests__/setup_management_workspace_adapter.test.ts`](../src/infrastructure/__tests__/setup_management_workspace_adapter.test.ts) · [`src/cli/__tests__/setup_management_adapter.test.ts`](../src/cli/__tests__/setup_management_adapter.test.ts) · [`src/cli/__tests__/web_setup_management_components.test.ts`](../src/cli/__tests__/web_setup_management_components.test.ts) · [`src/cli/__tests__/web_setup_runner_components.test.ts`](../src/cli/__tests__/web_setup_runner_components.test.ts) · [`src/cli/__tests__/setup_documentation_navigation.test.ts`](../src/cli/__tests__/setup_documentation_navigation.test.ts) · [`src/infrastructure/__tests__/setup_verification_action.test.ts`](../src/infrastructure/__tests__/setup_verification_action.test.ts) · [`src/application/policies/__tests__/setup_verification_onboarding_policy.test.ts`](../src/application/policies/__tests__/setup_verification_onboarding_policy.test.ts) · [`src/cli/__tests__/setup_verification_onboarding_components.test.ts`](../src/cli/__tests__/setup_verification_onboarding_components.test.ts) · [`src/application/usecases/setup/__tests__/setup_verification_onboarding_flow.test.ts`](../src/application/usecases/setup/__tests__/setup_verification_onboarding_flow.test.ts) -- User documentation: [`README.md`](../README.md) · [`docs/how-to-use.mdx`](../docs/how-to-use.mdx) · [`docs/authentication.mdx`](../docs/authentication.mdx) · [`docs/issues/assignees-and-projects.mdx`](../docs/issues/assignees-and-projects.mdx) · [`docs/pull-requests/guarded-approval.mdx`](../docs/pull-requests/guarded-approval.mdx) · [`docs/configuration.mdx`](../docs/configuration.mdx) · [`docs/configuration-checklist.mdx`](../docs/configuration-checklist.mdx) · [`docs/development/architecture.mdx`](../docs/development/architecture.mdx) · [`docs/development/setup-assistant-review.mdx`](../docs/development/setup-assistant-review.mdx) · [`docs/development/testing.mdx`](../docs/development/testing.mdx) · [`docs/dependency-rules.md`](../docs/dependency-rules.md) · [`docs/security-operations/security/self-hosted-runners.mdx`](../docs/security-operations/security/self-hosted-runners.mdx) · [`docs/security-operations/operations/troubleshooting.mdx`](../docs/security-operations/operations/troubleshooting.mdx) · [`docs/security-operations/operations/provisioning.mdx`](../docs/security-operations/operations/provisioning.mdx) · [`docs/setup-web.mdx`](../docs/setup-web.mdx) · [`docs/first-workflow.mdx`](../docs/first-workflow.mdx) · [`docs/using-the-docs.mdx`](../docs/using-the-docs.mdx) · [`docs/guides/index.mdx`](../docs/guides/index.mdx) · [`docs/guides/issues-and-branches.mdx`](../docs/guides/issues-and-branches.mdx) · [`docs/guides/review-pull-requests.mdx`](../docs/guides/review-pull-requests.mdx) · [`docs/guides/work-with-the-bot.mdx`](../docs/guides/work-with-the-bot.mdx) · [`docs/guides/releases-and-hotfixes.mdx`](../docs/guides/releases-and-hotfixes.mdx) · [`docs/security-operations/operations/verification.mdx`](../docs/security-operations/operations/verification.mdx) · [`docs/security-operations/operations/upgrade-rollback.mdx`](../docs/security-operations/operations/upgrade-rollback.mdx) +- User documentation: [`README.md`](../README.md) · [`docs/how-to-use.mdx`](../docs/how-to-use.mdx) · [`docs/authentication.mdx`](../docs/authentication.mdx) · [`docs/issues/assignees-and-projects.mdx`](../docs/issues/assignees-and-projects.mdx) · [`docs/pull-requests/guarded-approval.mdx`](../docs/pull-requests/guarded-approval.mdx) · [`docs/configuration.mdx`](../docs/configuration.mdx) · [`docs/configuration-checklist.mdx`](../docs/configuration-checklist.mdx) · [`docs/development/architecture.mdx`](../docs/development/architecture.mdx) · [`docs/development/setup-assistant-review.mdx`](../docs/development/setup-assistant-review.mdx) · [`docs/development/testing.mdx`](../docs/development/testing.mdx) · [`docs/dependency-rules.md`](../docs/dependency-rules.md) · [`docs/security-operations/security/self-hosted-runners.mdx`](../docs/security-operations/security/self-hosted-runners.mdx) · [`docs/security-operations/operations/troubleshooting.mdx`](../docs/security-operations/operations/troubleshooting.mdx) · [`docs/security-operations/operations/provisioning.mdx`](../docs/security-operations/operations/provisioning.mdx) · [`docs/setup-web.mdx`](../docs/setup-web.mdx) · [`docs/first-workflow.mdx`](../docs/first-workflow.mdx) · [`docs/using-the-docs.mdx`](../docs/using-the-docs.mdx) · [`docs/guides/index.mdx`](../docs/guides/index.mdx) · [`docs/guides/issues-and-branches.mdx`](../docs/guides/issues-and-branches.mdx) · [`docs/guides/review-pull-requests.mdx`](../docs/guides/review-pull-requests.mdx) · [`docs/guides/work-with-the-bot.mdx`](../docs/guides/work-with-the-bot.mdx) · [`docs/guides/releases-and-hotfixes.mdx`](../docs/guides/releases-and-hotfixes.mdx) · [`docs/security-operations/operations/verification.mdx`](../docs/security-operations/operations/verification.mdx) · [`docs/security-operations/operations/upgrade-rollback.mdx`](../docs/security-operations/operations/upgrade-rollback.mdx) · [`specs/github-browser-extension-control-center-and-setup.md`](./github-browser-extension-control-center-and-setup.md) ### `guided-bot-pat-onboarding` — Guided bot PAT onboarding @@ -265,6 +266,17 @@ debt or convert unknown historic intent into a design decision. - Tests: [`src/application/policies/__tests__/setup_questionnaire_policy.test.ts`](../src/application/policies/__tests__/setup_questionnaire_policy.test.ts) · [`src/application/policies/__tests__/bot_pull_request_analysis_policy.test.ts`](../src/application/policies/__tests__/bot_pull_request_analysis_policy.test.ts) · [`src/application/policies/__tests__/pull_request_approval_presentation_policy.test.ts`](../src/application/policies/__tests__/pull_request_approval_presentation_policy.test.ts) · [`src/application/policies/__tests__/pull_request_readiness_policy.test.ts`](../src/application/policies/__tests__/pull_request_readiness_policy.test.ts) · [`src/application/usecases/__tests__/read_copilot_status_workflow.test.ts`](../src/application/usecases/__tests__/read_copilot_status_workflow.test.ts) · [`src/application/policies/__tests__/setup_approval_doctor_policy.test.ts`](../src/application/policies/__tests__/setup_approval_doctor_policy.test.ts) · [`src/application/usecases/pull_request_approval/__tests__/observe_pull_request_approval_use_case.test.ts`](../src/application/usecases/pull_request_approval/__tests__/observe_pull_request_approval_use_case.test.ts) · [`src/application/usecases/setup/__tests__/doctor_use_case.test.ts`](../src/application/usecases/setup/__tests__/doctor_use_case.test.ts) · [`src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts`](../src/application/usecases/setup/__tests__/setup_wizard_use_case.test.ts) · [`src/application/usecases/steps/commit/bugbot/__tests__/synchronize_bugbot_review_presentation_use_case.test.ts`](../src/application/usecases/steps/commit/bugbot/__tests__/synchronize_bugbot_review_presentation_use_case.test.ts) · [`src/domain/__tests__/pull_request_approval.test.ts`](../src/domain/__tests__/pull_request_approval.test.ts) · [`src/domain/__tests__/setup_approval_workflow.test.ts`](../src/domain/__tests__/setup_approval_workflow.test.ts) · [`src/actions/__tests__/pull_request_approval_action.test.ts`](../src/actions/__tests__/pull_request_approval_action.test.ts) · [`src/actions/__tests__/pull_request_approval_logging.test.ts`](../src/actions/__tests__/pull_request_approval_logging.test.ts) · [`src/data/repository/pull_request/__tests__/approval_coverage_artifact.test.ts`](../src/data/repository/pull_request/__tests__/approval_coverage_artifact.test.ts) · [`src/data/repository/pull_request/__tests__/pull_request_approval_repository.test.ts`](../src/data/repository/pull_request/__tests__/pull_request_approval_repository.test.ts) · [`src/data/repository/pull_request/__tests__/pull_request_review_comment_command_repository.test.ts`](../src/data/repository/pull_request/__tests__/pull_request_review_comment_command_repository.test.ts) · [`src/infrastructure/__tests__/setup_approval_readiness_adapter.test.ts`](../src/infrastructure/__tests__/setup_approval_readiness_adapter.test.ts) · [`src/utils/__tests__/setup_files.test.ts`](../src/utils/__tests__/setup_files.test.ts) · [`src/tooling/__tests__/validate_workflow_contract.test.ts`](../src/tooling/__tests__/validate_workflow_contract.test.ts) · [`src/application/policies/__tests__/setup_token_permission_policy.test.ts`](../src/application/policies/__tests__/setup_token_permission_policy.test.ts) · [`src/application/usecases/__tests__/pull_request_readiness_workflow.test.ts`](../src/application/usecases/__tests__/pull_request_readiness_workflow.test.ts) · [`src/application/policies/__tests__/pull_request_readiness_presentation.test.ts`](../src/application/policies/__tests__/pull_request_readiness_presentation.test.ts) · [`src/application/usecases/__tests__/pull_request_readiness_security_integration.test.ts`](../src/application/usecases/__tests__/pull_request_readiness_security_integration.test.ts) · [`src/data/repository/pull_request/__tests__/pull_request_status_query_repository.test.ts`](../src/data/repository/pull_request/__tests__/pull_request_status_query_repository.test.ts) · [`src/infrastructure/composition/__tests__/pull_request_status_composition_root.test.ts`](../src/infrastructure/composition/__tests__/pull_request_status_composition_root.test.ts) · [`src/infrastructure/composition/__tests__/main_run_route_composition_root.test.ts`](../src/infrastructure/composition/__tests__/main_run_route_composition_root.test.ts) · [`src/application/policies/__tests__/setup_approval_operator_permissions.test.ts`](../src/application/policies/__tests__/setup_approval_operator_permissions.test.ts) · [`src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts`](../src/application/usecases/setup/__tests__/audit_configured_setup_pat_use_case.test.ts) · [`src/data/repository/pull_request/__tests__/approval_evidence_read.test.ts`](../src/data/repository/pull_request/__tests__/approval_evidence_read.test.ts) - User documentation: [`docs/authentication.mdx`](../docs/authentication.mdx) · [`docs/configuration.mdx`](../docs/configuration.mdx) · [`docs/configuration-checklist.mdx`](../docs/configuration-checklist.mdx) · [`docs/pull-requests/capabilities.mdx`](../docs/pull-requests/capabilities.mdx) · [`docs/pull-requests/guarded-approval.mdx`](../docs/pull-requests/guarded-approval.mdx) · [`docs/pull-requests/workflow-setup.mdx`](../docs/pull-requests/workflow-setup.mdx) · [`docs/issues/comment-commands.mdx`](../docs/issues/comment-commands.mdx) · [`docs/bugbot/configuration.mdx`](../docs/bugbot/configuration.mdx) · [`docs/development/architecture.mdx`](../docs/development/architecture.mdx) +### `github-browser-extension` — Complete GitHub productivity extension and integrated Copilot setup + +- Owner: Copilot maintainers +- Last verified: 2026-10-25 +- Specifications: [`specs/github-browser-extension.md`](./github-browser-extension.md) · [`specs/github-browser-extension-action-integration.md`](./github-browser-extension-action-integration.md) · [`specs/github-browser-extension-platforms-and-delivery.md`](./github-browser-extension-platforms-and-delivery.md) · [`specs/github-browser-extension-functional-catalog.md`](./github-browser-extension-functional-catalog.md) · [`specs/github-browser-extension-control-center-and-setup.md`](./github-browser-extension-control-center-and-setup.md) +- Workflows: Not applicable for this capability. +- Entrypoints: [`src/actions/github_action.ts`](../src/actions/github_action.ts) +- Core code: [`src/application/usecases/read_copilot_status_workflow.ts`](../src/application/usecases/read_copilot_status_workflow.ts) · [`src/application/ports/pull_request_status_read_ports.ts`](../src/application/ports/pull_request_status_read_ports.ts) +- Tests: [`src/application/usecases/__tests__/read_copilot_status_workflow.test.ts`](../src/application/usecases/__tests__/read_copilot_status_workflow.test.ts) +- User documentation: [`docs/development/specifications.mdx`](../docs/development/specifications.mdx) · [`docs/issues/comment-commands.mdx`](../docs/issues/comment-commands.mdx) · [`specs/browser-extension/manifest-v1.schema.json`](./manifest-v1.schema.json) · [`specs/browser-extension/status-v1.schema.json`](./status-v1.schema.json) · [`specs/browser-extension/examples/manifest-v1.json`](./manifest-v1.json) · [`specs/browser-extension/examples/status-pr-v1.json`](./status-pr-v1.json) · [`specs/browser-extension/examples/status-issue-v1.json`](./status-issue-v1.json) · [`specs/browser-extension/examples/status-invalid-head-v1.json`](./status-invalid-head-v1.json) · [`specs/browser-extension/feature-catalog.v1.json`](./feature-catalog.v1.json) · [`specs/browser-extension/feature-catalog.schema.json`](./feature-catalog.schema.json) · [`specs/browser-extension/requests-v2.schema.json`](./requests-v2.schema.json) · [`specs/browser-extension/examples/requests-v2.json`](./requests-v2.json) · [`specs/browser-extension/feature-catalog-index.schema.json`](./feature-catalog-index.schema.json) · [`specs/browser-extension/features/NAV.v1.json`](./NAV.v1.json) · [`specs/browser-extension/features/CODE.v1.json`](./CODE.v1.json) · [`specs/browser-extension/features/REVIEW.v1.json`](./REVIEW.v1.json) · [`specs/browser-extension/features/ISSUE.v1.json`](./ISSUE.v1.json) · [`specs/browser-extension/features/SEARCH.v1.json`](./SEARCH.v1.json) · [`specs/browser-extension/features/NOTIFY.v1.json`](./NOTIFY.v1.json) · [`specs/browser-extension/features/CI.v1.json`](./CI.v1.json) · [`specs/browser-extension/features/RELEASE.v1.json`](./RELEASE.v1.json) · [`specs/browser-extension/features/WORK.v1.json`](./WORK.v1.json) · [`specs/browser-extension/features/COPILOT.v1.json`](./COPILOT.v1.json) · [`specs/browser-extension/features/CENTER.v1.json`](./CENTER.v1.json) · [`specs/browser-extension/features/SETUP.v1.json`](./SETUP.v1.json) + ## Maintenance contract 1. Read the relevant SDD before changing a catalogued capability. diff --git a/specs/browser-extension/examples/manifest-v1.json b/specs/browser-extension/examples/manifest-v1.json new file mode 100644 index 000000000..f79c20118 --- /dev/null +++ b/specs/browser-extension/examples/manifest-v1.json @@ -0,0 +1,18 @@ +{ + "schemaVersion": 1, + "enabled": true, + "repositoryId": 1, + "producerActorId": 2, + "workflowPaths": [ + ".github/workflows/copilot_issue.yml", + ".github/workflows/copilot_pull_request.yml", + ".github/workflows/copilot_issue_comment.yml" + ], + "capabilities": [ + "context.v1", + "findings.v1", + "command-drafts.v1" + ], + "statusSchemaMajor": 1, + "publication": "current-status-comment" +} diff --git a/specs/browser-extension/examples/requests-v2.json b/specs/browser-extension/examples/requests-v2.json new file mode 100644 index 000000000..b6ecfdfc3 --- /dev/null +++ b/specs/browser-extension/examples/requests-v2.json @@ -0,0 +1,220 @@ +{ + "schemaVersion": 2, + "repositoryId": 1, + "producerActorId": 2, + "commands": [ + { + "name": "help", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "never" + }, + { + "name": "plan", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "clarify", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "estimate", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "test-plan", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "explain", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "diagnose", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "analyze", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "review", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "findings", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "recheck", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "may-run" + }, + { + "name": "sdd-diff", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "never" + }, + { + "name": "status", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "never" + }, + { + "name": "doctor", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "never" + }, + { + "name": "history", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "publication", + "agent": "never" + }, + { + "name": "description", + "contexts": [ + "conversation" + ], + "requiresWriteActor": false, + "requiresVerifiedBranch": false, + "effect": "pr-description", + "agent": "may-run" + }, + { + "name": "fix", + "contexts": [ + "review-thread" + ], + "requiresWriteActor": true, + "requiresVerifiedBranch": true, + "effect": "files", + "agent": "may-run" + }, + { + "name": "dismiss", + "contexts": [ + "conversation", + "review-thread" + ], + "requiresWriteActor": true, + "requiresVerifiedBranch": false, + "effect": "finding-state", + "agent": "never" + }, + { + "name": "implement", + "contexts": [ + "review-thread" + ], + "requiresWriteActor": true, + "requiresVerifiedBranch": true, + "effect": "files", + "agent": "may-run" + }, + { + "name": "remember", + "contexts": [ + "conversation", + "review-thread" + ], + "requiresWriteActor": true, + "requiresVerifiedBranch": true, + "effect": "files", + "agent": "never" + }, + { + "name": "sync-branch", + "contexts": [ + "conversation", + "review-thread" + ], + "requiresWriteActor": true, + "requiresVerifiedBranch": true, + "effect": "files", + "agent": "conditional" + } + ] +} diff --git a/specs/browser-extension/examples/status-invalid-head-v1.json b/specs/browser-extension/examples/status-invalid-head-v1.json new file mode 100644 index 000000000..0104ae976 --- /dev/null +++ b/specs/browser-extension/examples/status-invalid-head-v1.json @@ -0,0 +1,101 @@ +{ + "schemaVersion": 1, + "capabilities": [ + "context.v1", + "findings.v1", + "command-drafts.v1" + ], + "identity": { + "repositoryId": 1, + "kind": "pull-request", + "number": 158, + "headSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "baseSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "producer": { + "actorId": 2, + "runId": 300, + "attempt": 1, + "workflowPath": ".github/workflows/copilot_pull_request.yml", + "sourceCommit": "cccccccccccccccccccccccccccccccccccccccc", + "actionVersion": "3.0.0", + "configurationDigest": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + "publication": { + "commentId": 123, + "generation": 7, + "observedAt": "2026-10-25T10:42:00Z", + "outcome": "complete" + }, + "native": { + "state": "open", + "merged": false + }, + "lifecycle": { + "phase": "changes-requested", + "activity": "idle", + "waitingFor": "pr-author" + }, + "assessment": { + "state": "blocked", + "policyDigest": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "coverage": "complete", + "currentFindingCount": 1, + "nextAction": "inspect-findings" + }, + "links": [ + { + "kind": "issue", + "number": 142 + }, + { + "kind": "run", + "id": 300 + } + ], + "branch": { + "state": "verified", + "repositoryId": 1, + "ref": "feature/142-example", + "commitSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + "sdd": { + "state": "ready", + "path": "specs/example.md", + "commitSha": "ffffffffffffffffffffffffffffffffffffffff", + "pendingQuestionIds": [] + }, + "findings": { + "complete": true, + "total": 1, + "items": [ + { + "id": "F-1", + "reviewCommentId": 456, + "reviewId": 789, + "path": "src/example.ts", + "line": 12, + "severity": "high", + "state": "open", + "headSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "summary": "Validate the input before processing it." + } + ] + }, + "commands": [ + { + "name": "status", + "context": "conversation" + }, + { + "name": "analyze", + "context": "conversation" + }, + { + "name": "fix", + "context": "review-thread", + "findingId": "F-1", + "reviewCommentId": 456 + } + ] +} diff --git a/specs/browser-extension/examples/status-issue-v1.json b/specs/browser-extension/examples/status-issue-v1.json new file mode 100644 index 000000000..def8be3ba --- /dev/null +++ b/specs/browser-extension/examples/status-issue-v1.json @@ -0,0 +1,61 @@ +{ + "schemaVersion": 1, + "capabilities": [ + "context.v1", + "findings.v1", + "command-drafts.v1" + ], + "identity": { + "repositoryId": 1, + "kind": "issue", + "number": 142 + }, + "producer": { + "actorId": 2, + "runId": 300, + "attempt": 1, + "workflowPath": ".github/workflows/copilot_issue.yml", + "sourceCommit": "cccccccccccccccccccccccccccccccccccccccc", + "actionVersion": "3.0.0", + "configurationDigest": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + "publication": { + "commentId": 123, + "generation": 7, + "observedAt": "2026-10-25T10:42:00Z", + "outcome": "pending" + }, + "native": { + "state": "open", + "reason": null + }, + "lifecycle": { + "phase": "specifying", + "activity": "idle", + "waitingFor": "issue-author" + }, + "assessment": { + "state": "not-applicable", + "policyDigest": null, + "coverage": "unknown", + "currentFindingCount": null, + "nextAction": "open-question" + }, + "links": [], + "branch": null, + "sdd": { + "state": "awaiting-answers", + "path": "specs/example.md", + "commitSha": null, + "pendingQuestionIds": [ + "Q2" + ] + }, + "findings": null, + "commands": [ + { + "name": "status", + "context": "conversation" + } + ] +} diff --git a/specs/browser-extension/examples/status-pr-v1.json b/specs/browser-extension/examples/status-pr-v1.json new file mode 100644 index 000000000..06eb66fe8 --- /dev/null +++ b/specs/browser-extension/examples/status-pr-v1.json @@ -0,0 +1,101 @@ +{ + "schemaVersion": 1, + "capabilities": [ + "context.v1", + "findings.v1", + "command-drafts.v1" + ], + "identity": { + "repositoryId": 1, + "kind": "pull-request", + "number": 158, + "headSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "baseSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "producer": { + "actorId": 2, + "runId": 300, + "attempt": 1, + "workflowPath": ".github/workflows/copilot_pull_request.yml", + "sourceCommit": "cccccccccccccccccccccccccccccccccccccccc", + "actionVersion": "3.0.0", + "configurationDigest": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + "publication": { + "commentId": 123, + "generation": 7, + "observedAt": "2026-10-25T10:42:00Z", + "outcome": "complete" + }, + "native": { + "state": "open", + "merged": false + }, + "lifecycle": { + "phase": "changes-requested", + "activity": "idle", + "waitingFor": "pr-author" + }, + "assessment": { + "state": "blocked", + "policyDigest": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "coverage": "complete", + "currentFindingCount": 1, + "nextAction": "inspect-findings" + }, + "links": [ + { + "kind": "issue", + "number": 142 + }, + { + "kind": "run", + "id": 300 + } + ], + "branch": { + "state": "verified", + "repositoryId": 1, + "ref": "feature/142-example", + "commitSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + "sdd": { + "state": "ready", + "path": "specs/example.md", + "commitSha": "ffffffffffffffffffffffffffffffffffffffff", + "pendingQuestionIds": [] + }, + "findings": { + "complete": true, + "total": 1, + "items": [ + { + "id": "F-1", + "reviewCommentId": 456, + "reviewId": 789, + "path": "src/example.ts", + "line": 12, + "severity": "high", + "state": "open", + "headSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "summary": "Validate the input before processing it." + } + ] + }, + "commands": [ + { + "name": "status", + "context": "conversation" + }, + { + "name": "analyze", + "context": "conversation" + }, + { + "name": "fix", + "context": "review-thread", + "findingId": "F-1", + "reviewCommentId": 456 + } + ] +} diff --git a/specs/browser-extension/feature-catalog-index.schema.json b/specs/browser-extension/feature-catalog-index.schema.json new file mode 100644 index 000000000..d65e8ec42 --- /dev/null +++ b/specs/browser-extension/feature-catalog-index.schema.json @@ -0,0 +1,83 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://vypdev.github.io/copilot/specs/browser-extension/feature-catalog-index.schema.json", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "const": "./feature-catalog-index.schema.json" + }, + "schemaVersion": { + "const": 1 + }, + "status": { + "const": "proposed-product-contract" + }, + "runtimeVerified": { + "const": false + }, + "releaseContract": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "locales": { + "const": [ + "en", + "es", + "fr", + "pt" + ] + }, + "families": { + "type": "array", + "minItems": 12, + "maxItems": 12, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "enum": [ + "NAV", + "CODE", + "REVIEW", + "ISSUE", + "SEARCH", + "NOTIFY", + "CI", + "RELEASE", + "WORK", + "COPILOT", + "CENTER", + "SETUP" + ] + }, + "title": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "file": { + "type": "string", + "pattern": "^features/(NAV|CODE|REVIEW|ISSUE|SEARCH|NOTIFY|CI|RELEASE|WORK|COPILOT|CENTER|SETUP)\\.v1\\.json$" + } + }, + "required": [ + "id", + "title", + "file" + ] + } + } + }, + "required": [ + "$schema", + "schemaVersion", + "status", + "runtimeVerified", + "releaseContract", + "locales", + "families" + ] +} diff --git a/specs/browser-extension/feature-catalog.schema.json b/specs/browser-extension/feature-catalog.schema.json new file mode 100644 index 000000000..28579089c --- /dev/null +++ b/specs/browser-extension/feature-catalog.schema.json @@ -0,0 +1,280 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://vypdev.github.io/copilot/specs/browser-extension/feature-catalog.schema.json", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "const": "./feature-catalog.schema.json" + }, + "schemaVersion": { + "const": 1 + }, + "status": { + "const": "proposed-product-contract" + }, + "runtimeVerified": { + "const": false + }, + "releaseContract": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "locales": { + "const": [ + "en", + "es", + "fr", + "pt" + ] + }, + "families": { + "type": "array", + "minItems": 12, + "maxItems": 12, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "enum": [ + "NAV", + "CODE", + "REVIEW", + "ISSUE", + "SEARCH", + "NOTIFY", + "CI", + "RELEASE", + "WORK", + "COPILOT", + "CENTER", + "SETUP" + ] + }, + "title": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "features": { + "type": "array", + "minItems": 1, + "maxItems": 64, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "pattern": "^BEX-[A-Z]+-[0-9]{2}$" + }, + "family": { + "type": "string", + "enum": [ + "NAV", + "CODE", + "REVIEW", + "ISSUE", + "SEARCH", + "NOTIFY", + "CI", + "RELEASE", + "WORK", + "COPILOT", + "CENTER", + "SETUP" + ] + }, + "title": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "delivery": { + "const": "required-for-product-acceptance" + }, + "mode": { + "enum": [ + "local", + "settings", + "read", + "draft", + "write", + "setup", + "monitor" + ] + }, + "surface": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "userOutcome": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "boundaryAcceptance": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "permissionProfile": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "dataSource": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "freshnessRule": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "default": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "privacy": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "activation": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "coexistence": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "accessibility": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + }, + "optionalBrowserPermissions": { + "type": "array", + "maxItems": 2, + "uniqueItems": true, + "items": { + "enum": [ + "contextMenus", + "notifications", + "alarms" + ] + } + }, + "browsers": { + "const": [ + "chrome", + "firefox", + "safari" + ] + }, + "requirements": { + "type": "array", + "minItems": 1, + "maxItems": 4, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^CAT-[A-Z]+$" + } + }, + "documentation": { + "type": "array", + "minItems": 1, + "maxItems": 8, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^docs/browser-extension/[a-z-]+\\.mdx$" + } + }, + "tests": { + "type": "array", + "minItems": 3, + "maxItems": 7, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "pattern": "^bexp-[A-Z]+[0-9]{2}-C[0-9]{2}$" + }, + "scenario": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + } + }, + "required": [ + "id", + "scenario" + ] + } + }, + "nativeTarget": { + "enum": [ + "none", + "human-composer", + "control-handoff" + ] + } + }, + "required": [ + "id", + "family", + "title", + "delivery", + "mode", + "surface", + "userOutcome", + "boundaryAcceptance", + "permissionProfile", + "dataSource", + "freshnessRule", + "default", + "privacy", + "activation", + "coexistence", + "accessibility", + "optionalBrowserPermissions", + "browsers", + "requirements", + "documentation", + "tests", + "nativeTarget" + ] + } + } + }, + "required": [ + "id", + "title", + "features" + ] + } + } + }, + "required": [ + "$schema", + "schemaVersion", + "status", + "runtimeVerified", + "releaseContract", + "locales", + "families" + ] +} diff --git a/specs/browser-extension/feature-catalog.v1.json b/specs/browser-extension/feature-catalog.v1.json new file mode 100644 index 000000000..26d9c8cfe --- /dev/null +++ b/specs/browser-extension/feature-catalog.v1.json @@ -0,0 +1,75 @@ +{ + "$schema": "./feature-catalog-index.schema.json", + "schemaVersion": 1, + "status": "proposed-product-contract", + "runtimeVerified": false, + "releaseContract": "All registered features are required at general acceptance; delivery order is not a reduced product tier.", + "locales": [ + "en", + "es", + "fr", + "pt" + ], + "families": [ + { + "id": "NAV", + "title": "Navigation and context", + "file": "features/NAV.v1.json" + }, + { + "id": "CODE", + "title": "Code, files and diffs", + "file": "features/CODE.v1.json" + }, + { + "id": "REVIEW", + "title": "Pull requests and reviews", + "file": "features/REVIEW.v1.json" + }, + { + "id": "ISSUE", + "title": "Issues, discussions and collaboration", + "file": "features/ISSUE.v1.json" + }, + { + "id": "SEARCH", + "title": "Search and personal views", + "file": "features/SEARCH.v1.json" + }, + { + "id": "NOTIFY", + "title": "Notifications and attention", + "file": "features/NOTIFY.v1.json" + }, + { + "id": "CI", + "title": "Actions, checks and delivery evidence", + "file": "features/CI.v1.json" + }, + { + "id": "RELEASE", + "title": "Releases, tags and repository changes", + "file": "features/RELEASE.v1.json" + }, + { + "id": "WORK", + "title": "Personal workspaces and platform ergonomics", + "file": "features/WORK.v1.json" + }, + { + "id": "COPILOT", + "title": "Copilot Action integration", + "file": "features/COPILOT.v1.json" + }, + { + "id": "CENTER", + "title": "Local configuration and product experience", + "file": "features/CENTER.v1.json" + }, + { + "id": "SETUP", + "title": "Integrated Copilot setup and management", + "file": "features/SETUP.v1.json" + } + ] +} diff --git a/specs/browser-extension/features/CENTER.v1.json b/specs/browser-extension/features/CENTER.v1.json new file mode 100644 index 000000000..9be599ec8 --- /dev/null +++ b/specs/browser-extension/features/CENTER.v1.json @@ -0,0 +1,720 @@ +{ + "id": "CENTER", + "title": "Local configuration and product experience", + "features": [ + { + "id": "BEX-CENTER-01", + "family": "CENTER", + "title": "Full-page local control center", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Packaged extension options page", + "userOutcome": "Open a navigable application with overview, features, profiles, repositories, Copilot, setup, activity, privacy and help.", + "boundaryAcceptance": "The page loads from the extension package and remains useful offline without a CLI.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER01-C01", + "scenario": "Given the eligible packaged extension options page and verified input, choosing full-page local control center produces this observable result: Open a navigable application with overview, features, profiles, repositories, Copilot, setup, activity, privacy and help." + }, + { + "id": "bexp-CENTER01-C02", + "scenario": "For full-page local control center, exercise the concrete boundary: The page loads from the extension package and remains useful offline without a CLI." + }, + { + "id": "bexp-CENTER01-C03", + "scenario": "An invalid or future-schema change to full-page local control center preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER01-C04", + "scenario": "Full-page local control center survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-02", + "family": "CENTER", + "title": "Feature catalog and previews", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Features route", + "userOutcome": "Search, filter and preview every registered feature by surface, capability, permission, state and profile.", + "boundaryAcceptance": "A disabled feature explains its reason and cannot be silently enabled by a remote publication.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER02-C01", + "scenario": "Given the eligible features route and verified input, choosing feature catalog and previews produces this observable result: Search, filter and preview every registered feature by surface, capability, permission, state and profile." + }, + { + "id": "bexp-CENTER02-C02", + "scenario": "For feature catalog and previews, exercise the concrete boundary: A disabled feature explains its reason and cannot be silently enabled by a remote publication." + }, + { + "id": "bexp-CENTER02-C03", + "scenario": "An invalid or future-schema change to feature catalog and previews preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER02-C04", + "scenario": "Feature catalog and previews survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-03", + "family": "CENTER", + "title": "Profile editor and inheritance", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Profiles route", + "userOutcome": "Preview global, host/account, organization, repository and session overrides with provenance and reset.", + "boundaryAcceptance": "An unknown imported field or invalid cross-field combination leaves the previous complete profile intact.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER03-C01", + "scenario": "Given the eligible profiles route and verified input, choosing profile editor and inheritance produces this observable result: Preview global, host/account, organization, repository and session overrides with provenance and reset." + }, + { + "id": "bexp-CENTER03-C02", + "scenario": "For profile editor and inheritance, exercise the concrete boundary: An unknown imported field or invalid cross-field combination leaves the previous complete profile intact." + }, + { + "id": "bexp-CENTER03-C03", + "scenario": "An invalid or future-schema change to profile editor and inheritance preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER03-C04", + "scenario": "Profile editor and inheritance survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-04", + "family": "CENTER", + "title": "Repository connection manager", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Repositories route", + "userOutcome": "Connect, pause, switch and remove explicitly selected repositories with account/source identity shown.", + "boundaryAcceptance": "A repository rename uses its verified numeric identity and cannot expose a different private repository.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER04-C01", + "scenario": "Given the eligible repositories route and verified input, choosing repository connection manager produces this observable result: Connect, pause, switch and remove explicitly selected repositories with account/source identity shown." + }, + { + "id": "bexp-CENTER04-C02", + "scenario": "For repository connection manager, exercise the concrete boundary: A repository rename uses its verified numeric identity and cannot expose a different private repository." + }, + { + "id": "bexp-CENTER04-C03", + "scenario": "An invalid or future-schema change to repository connection manager preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER04-C04", + "scenario": "Repository connection manager survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-05", + "family": "CENTER", + "title": "Account and credential roles", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Connections route", + "userOutcome": "Manage at most five named session identities with separate selected-repository read and optional write roles.", + "boundaryAcceptance": "Switching identity invalidates private evidence and never reuses a token across hosts or purposes.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER05-C01", + "scenario": "Given the eligible connections route and verified input, choosing account and credential roles produces this observable result: Manage at most five named session identities with separate selected-repository read and optional write roles." + }, + { + "id": "bexp-CENTER05-C02", + "scenario": "For account and credential roles, exercise the concrete boundary: Switching identity invalidates private evidence and never reuses a token across hosts or purposes." + }, + { + "id": "bexp-CENTER05-C03", + "scenario": "An invalid or future-schema change to account and credential roles preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER05-C04", + "scenario": "Account and credential roles survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-06", + "family": "CENTER", + "title": "Permission and privacy inspector", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Privacy route", + "userOutcome": "Explain each browser/GitHub/CLI capability, granted scope, retention and revocation path.", + "boundaryAcceptance": "Unknown permission is displayed as unknown and optional capabilities stay off until granted.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER06-C01", + "scenario": "Given the eligible privacy route and verified input, choosing permission and privacy inspector produces this observable result: Explain each browser/GitHub/CLI capability, granted scope, retention and revocation path." + }, + { + "id": "bexp-CENTER06-C02", + "scenario": "For permission and privacy inspector, exercise the concrete boundary: Unknown permission is displayed as unknown and optional capabilities stay off until granted." + }, + { + "id": "bexp-CENTER06-C03", + "scenario": "An invalid or future-schema change to permission and privacy inspector preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER06-C04", + "scenario": "Permission and privacy inspector survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-07", + "family": "CENTER", + "title": "Shortcuts and command customization", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Shortcuts route", + "userOutcome": "Configure bounded bindings and favorites with native/OS conflict detection and reset.", + "boundaryAcceptance": "Editing shortcuts cannot capture secrets, typing composition or protected login interactions.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER07-C01", + "scenario": "Given the eligible shortcuts route and verified input, choosing shortcuts and command customization produces this observable result: Configure bounded bindings and favorites with native/OS conflict detection and reset." + }, + { + "id": "bexp-CENTER07-C02", + "scenario": "For shortcuts and command customization, exercise the concrete boundary: Editing shortcuts cannot capture secrets, typing composition or protected login interactions." + }, + { + "id": "bexp-CENTER07-C03", + "scenario": "An invalid or future-schema change to shortcuts and command customization preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER07-C04", + "scenario": "Shortcuts and command customization survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-08", + "family": "CENTER", + "title": "Settings backup and restore", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Data route", + "userOutcome": "Preview, validate and atomically import/export versioned nonsecret settings with migration and rollback.", + "boundaryAcceptance": "Private evidence, credentials and setup approval receipts are excluded from settings exports.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER08-C01", + "scenario": "Given the eligible data route and verified input, choosing settings backup and restore produces this observable result: Preview, validate and atomically import/export versioned nonsecret settings with migration and rollback." + }, + { + "id": "bexp-CENTER08-C02", + "scenario": "For settings backup and restore, exercise the concrete boundary: Private evidence, credentials and setup approval receipts are excluded from settings exports." + }, + { + "id": "bexp-CENTER08-C03", + "scenario": "An invalid or future-schema change to settings backup and restore preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER08-C04", + "scenario": "Settings backup and restore survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-09", + "family": "CENTER", + "title": "Local operation activity", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Activity route", + "userOutcome": "Inspect redacted operation intent, exact target, acknowledgement and observed completion separately.", + "boundaryAcceptance": "A timeout is unknown outcome and cannot be replaced by a fabricated success record.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER09-C01", + "scenario": "Given the eligible activity route and verified input, choosing local operation activity produces this observable result: Inspect redacted operation intent, exact target, acknowledgement and observed completion separately." + }, + { + "id": "bexp-CENTER09-C02", + "scenario": "For local operation activity, exercise the concrete boundary: A timeout is unknown outcome and cannot be replaced by a fabricated success record." + }, + { + "id": "bexp-CENTER09-C03", + "scenario": "An invalid or future-schema change to local operation activity preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER09-C04", + "scenario": "Local operation activity survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-10", + "family": "CENTER", + "title": "Feature diagnostics and recovery", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Diagnostics route", + "userOutcome": "Identify broken adapters, missing permissions and stale versions; disable one feature or reset owned state.", + "boundaryAcceptance": "Diagnostics never collect private code, tokens or full browsing history automatically.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER10-C01", + "scenario": "Given the eligible diagnostics route and verified input, choosing feature diagnostics and recovery produces this observable result: Identify broken adapters, missing permissions and stale versions; disable one feature or reset owned state." + }, + { + "id": "bexp-CENTER10-C02", + "scenario": "For feature diagnostics and recovery, exercise the concrete boundary: Diagnostics never collect private code, tokens or full browsing history automatically." + }, + { + "id": "bexp-CENTER10-C03", + "scenario": "An invalid or future-schema change to feature diagnostics and recovery preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER10-C04", + "scenario": "Feature diagnostics and recovery survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-11", + "family": "CENTER", + "title": "Appearance and accessibility preferences", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Appearance route", + "userOutcome": "Configure themes, density, readable text, reduced motion and contrast through accessible bounded controls.", + "boundaryAcceptance": "A setting cannot lower required contrast or remove keyboard access to a core action.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER11-C01", + "scenario": "Given the eligible appearance route and verified input, choosing appearance and accessibility preferences produces this observable result: Configure themes, density, readable text, reduced motion and contrast through accessible bounded controls." + }, + { + "id": "bexp-CENTER11-C02", + "scenario": "For appearance and accessibility preferences, exercise the concrete boundary: A setting cannot lower required contrast or remove keyboard access to a core action." + }, + { + "id": "bexp-CENTER11-C03", + "scenario": "An invalid or future-schema change to appearance and accessibility preferences preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER11-C04", + "scenario": "Appearance and accessibility preferences survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-12", + "family": "CENTER", + "title": "Language and terminology", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Language route", + "userOutcome": "Provide complete English, Spanish, French and Portuguese with atomic fallback and separate Action-source language.", + "boundaryAcceptance": "A missing message cannot produce a partly translated confirmation or reinterpret command IDs.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER12-C01", + "scenario": "Given the eligible language route and verified input, choosing language and terminology produces this observable result: Provide complete English, Spanish, French and Portuguese with atomic fallback and separate Action-source language." + }, + { + "id": "bexp-CENTER12-C02", + "scenario": "For language and terminology, exercise the concrete boundary: A missing message cannot produce a partly translated confirmation or reinterpret command IDs." + }, + { + "id": "bexp-CENTER12-C03", + "scenario": "An invalid or future-schema change to language and terminology preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER12-C04", + "scenario": "Language and terminology survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-13", + "family": "CENTER", + "title": "Onboarding, updates and release notes", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Welcome and About routes", + "userOutcome": "Explain value, selected profile, permissions and changes with resumable nonsecret onboarding and verified update links.", + "boundaryAcceptance": "An update never expands grants or changes a user's selected profile without review.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER13-C01", + "scenario": "Given the eligible welcome and about routes and verified input, choosing onboarding, updates and release notes produces this observable result: Explain value, selected profile, permissions and changes with resumable nonsecret onboarding and verified update links." + }, + { + "id": "bexp-CENTER13-C02", + "scenario": "For onboarding, updates and release notes, exercise the concrete boundary: An update never expands grants or changes a user's selected profile without review." + }, + { + "id": "bexp-CENTER13-C03", + "scenario": "An invalid or future-schema change to onboarding, updates and release notes preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER13-C04", + "scenario": "Onboarding, updates and release notes survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CENTER-14", + "family": "CENTER", + "title": "Privacy controls and reset center", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Privacy and recovery routes", + "userOutcome": "Pause all features, disconnect credentials, clear caches and reset selected settings with explicit scope.", + "boundaryAcceptance": "A data reset preserves unrelated GitHub content and requires review before deleting authored local notes.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "available-on-local-center", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CENTER" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CENTER14-C01", + "scenario": "Given the eligible privacy and recovery routes and verified input, choosing privacy controls and reset center produces this observable result: Pause all features, disconnect credentials, clear caches and reset selected settings with explicit scope." + }, + { + "id": "bexp-CENTER14-C02", + "scenario": "For privacy controls and reset center, exercise the concrete boundary: A data reset preserves unrelated GitHub content and requires review before deleting authored local notes." + }, + { + "id": "bexp-CENTER14-C03", + "scenario": "An invalid or future-schema change to privacy controls and reset center preserves the previous complete settings revision." + }, + { + "id": "bexp-CENTER14-C04", + "scenario": "Privacy controls and reset center survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/CI.v1.json b/specs/browser-extension/features/CI.v1.json new file mode 100644 index 000000000..be6c6a299 --- /dev/null +++ b/specs/browser-extension/features/CI.v1.json @@ -0,0 +1,544 @@ +{ + "id": "CI", + "title": "Actions, checks and delivery evidence", + "features": [ + { + "id": "BEX-CI-01", + "family": "CI", + "title": "Check hierarchy overview", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request and commit checks", + "userOutcome": "Show canonical check/status outcomes; classify required/advisory only with current requirement evidence, otherwise unknown.", + "boundaryAcceptance": "Checks/Commit statuses read are optional feature grants; denied or partial sources never become zero failures, and skipped legs never count as successful required evidence.", + "permissionProfile": "selected-repository-read", + "dataSource": "Integration 11.2: Checks read check-runs at the full head SHA, Commit statuses read contexts, and explicitly labeled loaded native requirement evidence; Action assessment remains separate.", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI01-C01", + "scenario": "With selected-repository Checks read and Commit statuses read, canonical full-head check runs and status contexts are shown separately; current native requirement evidence classifies requiredness and its absence yields unknown." + }, + { + "id": "bexp-CI01-C02", + "scenario": "A skipped matrix leg never becomes successful required evidence, and a successful advisory/unknown-policy check never establishes merge readiness." + }, + { + "id": "bexp-CI01-C03", + "scenario": "Denied Checks/Commit statuses read, truncated pagination or stale evidence shows source-specific unavailable/partial states with native links, retaining only labeled loaded-native rows and never claiming zero failures." + }, + { + "id": "bexp-CI01-C04", + "scenario": "Changing the selected repository/account/revision while check hierarchy overview is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-02", + "family": "CI", + "title": "Run and attempt navigation", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Actions and PR checks", + "userOutcome": "Navigate the exact workflow run, attempt, job and annotation referenced by a result.", + "boundaryAcceptance": "A later attempt cannot silently replace the source of an older finding.", + "permissionProfile": "selected-repository-read", + "dataSource": "Integration 11.2: Actions read run/attempt/job identities and, when granted, Checks read check identities; external check IDs are not Actions IDs.", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI02-C01", + "scenario": "Given the eligible actions and pr checks and verified input, choosing run and attempt navigation produces this observable result: Navigate the exact workflow run, attempt, job and annotation referenced by a result." + }, + { + "id": "bexp-CI02-C02", + "scenario": "For run and attempt navigation, exercise the concrete boundary: A later attempt cannot silently replace the source of an older finding." + }, + { + "id": "bexp-CI02-C03", + "scenario": "A denied, truncated or expired source for run and attempt navigation shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CI02-C04", + "scenario": "Changing the selected repository/account/revision while run and attempt navigation is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-03", + "family": "CI", + "title": "Annotation navigator", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Check output and changed files", + "userOutcome": "Group annotations from the verified Checks read endpoint by file/severity with exact line/revision mapping.", + "boundaryAcceptance": "Missing Checks read shows unavailable/native loaded-only fallback; unmapped or truncated annotations remain explicit partial/unplaced evidence.", + "permissionProfile": "selected-repository-read", + "dataSource": "Integration 11.2: GET check-runs/{verified-id}/annotations with optional selected-repository Checks read, parent repository/full-head validation and bounded pagination; loaded DOM is an explicit subset.", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI03-C01", + "scenario": "With Checks read granted, verify the selected check parent repository/full head, read canonical annotations through its fixed endpoint and group by file/severity with exact line mapping; the Action projection is not an annotation source." + }, + { + "id": "bexp-CI03-C02", + "scenario": "An unmapped line or a collection exceeding three 100-item pages or shared byte/request limits remains partial with unplaced evidence and an explicit budgeted continuation." + }, + { + "id": "bexp-CI03-C03", + "scenario": "Missing/denied Checks read shows unavailable with a native destination or labeled loaded-only native evidence; expired/partial data never becomes a complete or empty annotation inventory." + }, + { + "id": "bexp-CI03-C04", + "scenario": "Changing the selected repository/account/revision while annotation navigator is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-04", + "family": "CI", + "title": "Failure comparison", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Workflow run history", + "userOutcome": "Compare selected attempts' observed outcomes and changed failure locations.", + "boundaryAcceptance": "The extension does not diagnose causation from a single timing correlation.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI04-C01", + "scenario": "Given the eligible workflow run history and verified input, choosing failure comparison produces this observable result: Compare selected attempts' observed outcomes and changed failure locations." + }, + { + "id": "bexp-CI04-C02", + "scenario": "For failure comparison, exercise the concrete boundary: The extension does not diagnose causation from a single timing correlation." + }, + { + "id": "bexp-CI04-C03", + "scenario": "A denied, truncated or expired source for failure comparison shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CI04-C04", + "scenario": "Changing the selected repository/account/revision while failure comparison is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-05", + "family": "CI", + "title": "Run retry controls", + "delivery": "required-for-product-acceptance", + "mode": "write", + "surface": "Workflow run or failed job", + "userOutcome": "Preview exact repository, workflow, run/attempt and failed-job scope, then request one supported retry.", + "boundaryAcceptance": "An uncertain response is reconciled through canonical run state before any repeated request.", + "permissionProfile": "explicit-user-write", + "dataSource": "canonical target, separately authorized write identity and reviewed intent", + "freshnessRule": "final live target/permission/approval fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI05-C01", + "scenario": "Given the eligible workflow run or failed job and verified input, choosing run retry controls produces this observable result: Preview exact repository, workflow, run/attempt and failed-job scope, then request one supported retry." + }, + { + "id": "bexp-CI05-C02", + "scenario": "For run retry controls, exercise the concrete boundary: An uncertain response is reconciled through canonical run state before any repeated request." + }, + { + "id": "bexp-CI05-C03", + "scenario": "Opening or refreshing run retry controls performs no write; a denied write grant leaves the repository unchanged." + }, + { + "id": "bexp-CI05-C04", + "scenario": "A changed target/head/current value after the preview for run retry controls invalidates approval and requires review again." + }, + { + "id": "bexp-CI05-C05", + "scenario": "A timeout after submitting run retry controls is reconciled through canonical state and is never retried blindly." + }, + { + "id": "bexp-CI05-C06", + "scenario": "A duplicate click or restored tab for run retry controls cannot reuse a consumed operation intent." + }, + { + "id": "bexp-CI05-C07", + "scenario": "After the provider accepts one retry, delayed visibility of the new attempt shows acknowledged and awaiting canonical verification; the extension neither invents an attempt number nor sends another retry." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-06", + "family": "CI", + "title": "Run cancellation controls", + "delivery": "required-for-product-acceptance", + "mode": "write", + "surface": "Active workflow run", + "userOutcome": "Confirm the exact running attempt and explain retained side effects before cancellation.", + "boundaryAcceptance": "A completed or replaced attempt invalidates the confirmation rather than cancelling another run.", + "permissionProfile": "explicit-user-write", + "dataSource": "canonical target, separately authorized write identity and reviewed intent", + "freshnessRule": "final live target/permission/approval fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI06-C01", + "scenario": "Given the eligible active workflow run and verified input, choosing run cancellation controls produces this observable result: Confirm the exact running attempt and explain retained side effects before cancellation." + }, + { + "id": "bexp-CI06-C02", + "scenario": "For run cancellation controls, exercise the concrete boundary: A completed or replaced attempt invalidates the confirmation rather than cancelling another run." + }, + { + "id": "bexp-CI06-C03", + "scenario": "Opening or refreshing run cancellation controls performs no write; a denied write grant leaves the repository unchanged." + }, + { + "id": "bexp-CI06-C04", + "scenario": "A changed target/head/current value after the preview for run cancellation controls invalidates approval and requires review again." + }, + { + "id": "bexp-CI06-C05", + "scenario": "A timeout after submitting run cancellation controls is reconciled through canonical state and is never retried blindly." + }, + { + "id": "bexp-CI06-C06", + "scenario": "A duplicate click or restored tab for run cancellation controls cannot reuse a consumed operation intent." + }, + { + "id": "bexp-CI06-C07", + "scenario": "After cancellation is accepted, the selected attempt may still run or complete naturally; show its verified terminal outcome and retained side effects without claiming cancellation succeeded or issuing a second cancel." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-07", + "family": "CI", + "title": "Workflow dispatch preparation", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Actions workflow page", + "userOutcome": "Prepare a reviewed native workflow-dispatch form with exact ref and supported inputs.", + "boundaryAcceptance": "Hidden inputs, deployment policy and unknown workflow identity block an invented execution route.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI07-C01", + "scenario": "Given the eligible actions workflow page and verified input, choosing workflow dispatch preparation produces this observable result: Prepare a reviewed native workflow-dispatch form with exact ref and supported inputs." + }, + { + "id": "bexp-CI07-C02", + "scenario": "For workflow dispatch preparation, exercise the concrete boundary: Hidden inputs, deployment policy and unknown workflow identity block an invented execution route." + }, + { + "id": "bexp-CI07-C03", + "scenario": "Opening workflow dispatch preparation preserves the current native selection/input and requires the human's native confirmation; cancel performs no mutation." + }, + { + "id": "bexp-CI07-C04", + "scenario": "A changed target, permission or selection while workflow dispatch preparation is being prepared invalidates the handoff and refreshes its exact scope." + }, + { + "id": "bexp-CI07-C05", + "scenario": "Keyboard-only use of workflow dispatch preparation announces the exact native destination and effect, returns focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-CI-08", + "family": "CI", + "title": "Artifacts and job summaries", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Workflow runs", + "userOutcome": "Navigate verified summaries and user-selected artifacts with size/type/source preview.", + "boundaryAcceptance": "Expired artifacts or redirected downloads never receive an unrelated credential.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI08-C01", + "scenario": "Given the eligible workflow runs and verified input, choosing artifacts and job summaries produces this observable result: Navigate verified summaries and user-selected artifacts with size/type/source preview." + }, + { + "id": "bexp-CI08-C02", + "scenario": "For artifacts and job summaries, exercise the concrete boundary: Expired artifacts or redirected downloads never receive an unrelated credential." + }, + { + "id": "bexp-CI08-C03", + "scenario": "A denied, truncated or expired source for artifacts and job summaries shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CI08-C04", + "scenario": "Changing the selected repository/account/revision while artifacts and job summaries is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-09", + "family": "CI", + "title": "Queue, runner and waiting explanations", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Run and PR status", + "userOutcome": "Distinguish queued, waiting for environment approval, running and unavailable runner evidence.", + "boundaryAcceptance": "Unavailable runner permissions cannot be converted into zero capacity or a failed workflow.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI09-C01", + "scenario": "Given the eligible run and pr status and verified input, choosing queue, runner and waiting explanations produces this observable result: Distinguish queued, waiting for environment approval, running and unavailable runner evidence." + }, + { + "id": "bexp-CI09-C02", + "scenario": "For queue, runner and waiting explanations, exercise the concrete boundary: Unavailable runner permissions cannot be converted into zero capacity or a failed workflow." + }, + { + "id": "bexp-CI09-C03", + "scenario": "A denied, truncated or expired source for queue, runner and waiting explanations shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CI09-C04", + "scenario": "Changing the selected repository/account/revision while queue, runner and waiting explanations is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CI-10", + "family": "CI", + "title": "Performance and reliability trends", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Selected workflow history", + "userOutcome": "Summarize a bounded explicit run sample with percentile, cancellation and missing-sample disclosure.", + "boundaryAcceptance": "Sampling bias and incomplete history prevent claims about repository-wide reliability.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CI" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CI10-C01", + "scenario": "Given the eligible selected workflow history and verified input, choosing performance and reliability trends produces this observable result: Summarize a bounded explicit run sample with percentile, cancellation and missing-sample disclosure." + }, + { + "id": "bexp-CI10-C02", + "scenario": "For performance and reliability trends, exercise the concrete boundary: Sampling bias and incomplete history prevent claims about repository-wide reliability." + }, + { + "id": "bexp-CI10-C03", + "scenario": "A denied, truncated or expired source for performance and reliability trends shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CI10-C04", + "scenario": "Changing the selected repository/account/revision while performance and reliability trends is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/CODE.v1.json b/specs/browser-extension/features/CODE.v1.json new file mode 100644 index 000000000..ffeb53358 --- /dev/null +++ b/specs/browser-extension/features/CODE.v1.json @@ -0,0 +1,684 @@ +{ + "id": "CODE", + "title": "Code, files and diffs", + "features": [ + { + "id": "BEX-CODE-01", + "family": "CODE", + "title": "File tree and outline navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Files changed and code views", + "userOutcome": "Navigate loaded file groups, symbols exposed by native GitHub and exact path search with visible loaded-scope counts.", + "boundaryAcceptance": "Virtualized or unloaded files are labeled as a subset rather than silently omitted.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE01-C01", + "scenario": "Given the eligible files changed and code views and verified input, choosing file tree and outline navigation produces this observable result: Navigate loaded file groups, symbols exposed by native GitHub and exact path search with visible loaded-scope counts." + }, + { + "id": "bexp-CODE01-C02", + "scenario": "For file tree and outline navigation, exercise the concrete boundary: Virtualized or unloaded files are labeled as a subset rather than silently omitted." + }, + { + "id": "bexp-CODE01-C03", + "scenario": "After file tree and outline navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-02", + "family": "CODE", + "title": "Next and previous changed file", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Pull request Files changed", + "userOutcome": "Move among eligible files with a keyboard-accessible position indicator and return-to-origin action.", + "boundaryAcceptance": "Disposed file anchors cannot receive focus after a soft navigation.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE02-C01", + "scenario": "Given the eligible pull request files changed and verified input, choosing next and previous changed file produces this observable result: Move among eligible files with a keyboard-accessible position indicator and return-to-origin action." + }, + { + "id": "bexp-CODE02-C02", + "scenario": "For next and previous changed file, exercise the concrete boundary: Disposed file anchors cannot receive focus after a soft navigation." + }, + { + "id": "bexp-CODE02-C03", + "scenario": "After next and previous changed file mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-03", + "family": "CODE", + "title": "Generated-file focus", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Pull request diffs", + "userOutcome": "Hide explicitly classified generated files with hidden counts and immediate restore.", + "boundaryAcceptance": "Filename suffix alone never establishes generated status or hides a required finding.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE03-C01", + "scenario": "Given the eligible pull request diffs and verified input, choosing generated-file focus produces this observable result: Hide explicitly classified generated files with hidden counts and immediate restore." + }, + { + "id": "bexp-CODE03-C02", + "scenario": "For generated-file focus, exercise the concrete boundary: Filename suffix alone never establishes generated status or hides a required finding." + }, + { + "id": "bexp-CODE03-C03", + "scenario": "After generated-file focus mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-04", + "family": "CODE", + "title": "Whitespace and indentation readability", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Code and diffs", + "userOutcome": "Toggle visual whitespace markers, indentation guides and tab width without changing copied source.", + "boundaryAcceptance": "Native code selection, line anchors and diff meaning remain intact.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE04-C01", + "scenario": "Given the eligible code and diffs and verified input, choosing whitespace and indentation readability produces this observable result: Toggle visual whitespace markers, indentation guides and tab width without changing copied source." + }, + { + "id": "bexp-CODE04-C02", + "scenario": "For whitespace and indentation readability, exercise the concrete boundary: Native code selection, line anchors and diff meaning remain intact." + }, + { + "id": "bexp-CODE04-C03", + "scenario": "After whitespace and indentation readability mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-05", + "family": "CODE", + "title": "Readability and wrap profiles", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Code, Markdown and diffs", + "userOutcome": "Apply per-surface font size, line height, wrapping and density through bounded design tokens.", + "boundaryAcceptance": "Unsupported combinations retain horizontal access and never clip native controls.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE05-C01", + "scenario": "Given the eligible code, markdown and diffs and verified input, choosing readability and wrap profiles produces this observable result: Apply per-surface font size, line height, wrapping and density through bounded design tokens." + }, + { + "id": "bexp-CODE05-C02", + "scenario": "For readability and wrap profiles, exercise the concrete boundary: Unsupported combinations retain horizontal access and never clip native controls." + }, + { + "id": "bexp-CODE05-C03", + "scenario": "An invalid or future-schema change to readability and wrap profiles preserves the previous complete settings revision." + }, + { + "id": "bexp-CODE05-C04", + "scenario": "Readability and wrap profiles survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-06", + "family": "CODE", + "title": "Copy patch and changed fragment", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Diff hunks", + "userOutcome": "Prepare a bounded patch or selected fragment with source revision and explicit inclusion preview.", + "boundaryAcceptance": "Truncated or partially loaded hunks cannot be presented as the complete patch.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE06-C01", + "scenario": "Given the eligible diff hunks and verified input, choosing copy patch and changed fragment produces this observable result: Prepare a bounded patch or selected fragment with source revision and explicit inclusion preview." + }, + { + "id": "bexp-CODE06-C02", + "scenario": "For copy patch and changed fragment, exercise the concrete boundary: Truncated or partially loaded hunks cannot be presented as the complete patch." + }, + { + "id": "bexp-CODE06-C03", + "scenario": "After copy patch and changed fragment mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-07", + "family": "CODE", + "title": "Rename and binary context", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Changed files", + "userOutcome": "Explain verified rename relationships and binary or image changes with native source links.", + "boundaryAcceptance": "An unavailable blob or similarity estimate is not proof of identical content.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE07-C01", + "scenario": "Given the eligible changed files and verified input, choosing rename and binary context produces this observable result: Explain verified rename relationships and binary or image changes with native source links." + }, + { + "id": "bexp-CODE07-C02", + "scenario": "For rename and binary context, exercise the concrete boundary: An unavailable blob or similarity estimate is not proof of identical content." + }, + { + "id": "bexp-CODE07-C03", + "scenario": "A denied, truncated or expired source for rename and binary context shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CODE07-C04", + "scenario": "Changing the selected repository/account/revision while rename and binary context is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-08", + "family": "CODE", + "title": "File history and blame links", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Code and diffs", + "userOutcome": "Open native history or blame at the observed file/ref and preserve line context where supported.", + "boundaryAcceptance": "A line that cannot be mapped opens the file with an explicit mapping limitation.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE08-C01", + "scenario": "Given the eligible code and diffs and verified input, choosing file history and blame links produces this observable result: Open native history or blame at the observed file/ref and preserve line context where supported." + }, + { + "id": "bexp-CODE08-C02", + "scenario": "For file history and blame links, exercise the concrete boundary: A line that cannot be mapped opens the file with an explicit mapping limitation." + }, + { + "id": "bexp-CODE08-C03", + "scenario": "After file history and blame links mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-09", + "family": "CODE", + "title": "Symbol and text navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Rendered code", + "userOutcome": "Search loaded text and native symbol anchors with match counts and next/previous controls.", + "boundaryAcceptance": "Search does not execute repository code or infer cross-file symbol resolution.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE09-C01", + "scenario": "Given the eligible rendered code and verified input, choosing symbol and text navigation produces this observable result: Search loaded text and native symbol anchors with match counts and next/previous controls." + }, + { + "id": "bexp-CODE09-C02", + "scenario": "For symbol and text navigation, exercise the concrete boundary: Search does not execute repository code or infer cross-file symbol resolution." + }, + { + "id": "bexp-CODE09-C03", + "scenario": "After symbol and text navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-10", + "family": "CODE", + "title": "Review progress markers", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Pull request files", + "userOutcome": "Track personal visited files against exact head/base identity and show what remains.", + "boundaryAcceptance": "A changed revision invalidates only affected progress and never alters GitHub review state.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE10-C01", + "scenario": "Given the eligible pull request files and verified input, choosing review progress markers produces this observable result: Track personal visited files against exact head/base identity and show what remains." + }, + { + "id": "bexp-CODE10-C02", + "scenario": "For review progress markers, exercise the concrete boundary: A changed revision invalidates only affected progress and never alters GitHub review state." + }, + { + "id": "bexp-CODE10-C03", + "scenario": "An invalid or future-schema change to review progress markers preserves the previous complete settings revision." + }, + { + "id": "bexp-CODE10-C04", + "scenario": "Review progress markers survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-11", + "family": "CODE", + "title": "File type and path filters", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Diff and directory lists", + "userOutcome": "Combine extension, directory and text filters while exposing hidden content and reset.", + "boundaryAcceptance": "Filtering cannot suppress native security or required-check blockers.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE11-C01", + "scenario": "Given the eligible diff and directory lists and verified input, choosing file type and path filters produces this observable result: Combine extension, directory and text filters while exposing hidden content and reset." + }, + { + "id": "bexp-CODE11-C02", + "scenario": "For file type and path filters, exercise the concrete boundary: Filtering cannot suppress native security or required-check blockers." + }, + { + "id": "bexp-CODE11-C03", + "scenario": "After file type and path filters mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-12", + "family": "CODE", + "title": "Raw, rendered and download navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "File headers", + "userOutcome": "Offer native raw, rendered and download destinations with the exact source identity shown.", + "boundaryAcceptance": "An executable download is never opened or run automatically.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE12-C01", + "scenario": "Given the eligible file headers and verified input, choosing raw, rendered and download navigation produces this observable result: Offer native raw, rendered and download destinations with the exact source identity shown." + }, + { + "id": "bexp-CODE12-C02", + "scenario": "For raw, rendered and download navigation, exercise the concrete boundary: An executable download is never opened or run automatically." + }, + { + "id": "bexp-CODE12-C03", + "scenario": "After raw, rendered and download navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-13", + "family": "CODE", + "title": "Dependency and configuration context", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Manifests and lockfile changes", + "userOutcome": "Link observed package names, version changes and configuration references to allowlisted native evidence.", + "boundaryAcceptance": "A package name alone cannot infer vulnerability status or fetch arbitrary registry URLs.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE13-C01", + "scenario": "Given the eligible manifests and lockfile changes and verified input, choosing dependency and configuration context produces this observable result: Link observed package names, version changes and configuration references to allowlisted native evidence." + }, + { + "id": "bexp-CODE13-C02", + "scenario": "For dependency and configuration context, exercise the concrete boundary: A package name alone cannot infer vulnerability status or fetch arbitrary registry URLs." + }, + { + "id": "bexp-CODE13-C03", + "scenario": "A denied, truncated or expired source for dependency and configuration context shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-CODE13-C04", + "scenario": "Changing the selected repository/account/revision while dependency and configuration context is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-CODE-14", + "family": "CODE", + "title": "Review checkpoints and return position", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Long diffs", + "userOutcome": "Resume an explicit per-revision review checkpoint with scroll and focused file context.", + "boundaryAcceptance": "A missing or rewritten file offers a safe fallback without inventing progress.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-CODE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-CODE14-C01", + "scenario": "Given the eligible long diffs and verified input, choosing review checkpoints and return position produces this observable result: Resume an explicit per-revision review checkpoint with scroll and focused file context." + }, + { + "id": "bexp-CODE14-C02", + "scenario": "For review checkpoints and return position, exercise the concrete boundary: A missing or rewritten file offers a safe fallback without inventing progress." + }, + { + "id": "bexp-CODE14-C03", + "scenario": "An invalid or future-schema change to review checkpoints and return position preserves the previous complete settings revision." + }, + { + "id": "bexp-CODE14-C04", + "scenario": "Review checkpoints and return position survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/COPILOT.v1.json b/specs/browser-extension/features/COPILOT.v1.json new file mode 100644 index 000000000..9b043e927 --- /dev/null +++ b/specs/browser-extension/features/COPILOT.v1.json @@ -0,0 +1,1294 @@ +{ + "id": "COPILOT", + "title": "Copilot Action integration", + "features": [ + { + "id": "BEX-COPILOT-01", + "family": "COPILOT", + "title": "Issue-to-release control tower", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Issue, PR and control center", + "userOutcome": "Show verified issue, SDD, branch, PR, run, promotion, publication and reconciliation links in one journey.", + "boundaryAcceptance": "Partial publication remains published even if later synchronization fails.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT01-C01", + "scenario": "Given the eligible issue, pr and control center and verified input, choosing issue-to-release control tower produces this observable result: Show verified issue, SDD, branch, PR, run, promotion, publication and reconciliation links in one journey." + }, + { + "id": "bexp-COPILOT01-C02", + "scenario": "For issue-to-release control tower, exercise the concrete boundary: Partial publication remains published even if later synchronization fails." + }, + { + "id": "bexp-COPILOT01-C03", + "scenario": "A denied, truncated or expired source for issue-to-release control tower shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT01-C04", + "scenario": "Changing the selected repository/account/revision while issue-to-release control tower is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-02", + "family": "COPILOT", + "title": "SDD question workbench", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Issue clarification card", + "userOutcome": "Prepare numbered answers for the current verified questions with owner and revision context.", + "boundaryAcceptance": "A changed question round invalidates prepared answers rather than submitting stale decisions.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT02-C01", + "scenario": "Given the eligible issue clarification card and verified input, choosing sdd question workbench produces this observable result: Prepare numbered answers for the current verified questions with owner and revision context." + }, + { + "id": "bexp-COPILOT02-C02", + "scenario": "For sdd question workbench, exercise the concrete boundary: A changed question round invalidates prepared answers rather than submitting stale decisions." + }, + { + "id": "bexp-COPILOT02-C03", + "scenario": "SDD question workbench with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT02-C04", + "scenario": "A changed target or revoked capability before sdd question workbench prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT02-C05", + "scenario": "Keyboard-only use of sdd question workbench announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-03", + "family": "COPILOT", + "title": "SDD publication comparison", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Issue and PR SDD panel", + "userOutcome": "Prepare the supported sdd-diff request and open verified first/current publications.", + "boundaryAcceptance": "Unavailable historical evidence cannot be inferred from a filename or an unverified comment.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT03-C01", + "scenario": "Given the eligible issue and pr sdd panel and verified input, choosing sdd publication comparison produces this observable result: Prepare the supported sdd-diff request and open verified first/current publications." + }, + { + "id": "bexp-COPILOT03-C02", + "scenario": "For sdd publication comparison, exercise the concrete boundary: Unavailable historical evidence cannot be inferred from a filename or an unverified comment." + }, + { + "id": "bexp-COPILOT03-C03", + "scenario": "SDD publication comparison with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT03-C04", + "scenario": "A changed target or revoked capability before sdd publication comparison prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT03-C05", + "scenario": "Keyboard-only use of sdd publication comparison announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-04", + "family": "COPILOT", + "title": "Issue admission and start guidance", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Installed issue forms and issue sidebar", + "userOutcome": "Guide enabled issue-kind forms and the native in-progress transition with the Action as branch owner.", + "boundaryAcceptance": "The extension never creates, renames or deletes an Action-managed branch.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT04-C01", + "scenario": "Given the eligible installed issue forms and issue sidebar and verified input, choosing issue admission and start guidance produces this observable result: Guide enabled issue-kind forms and the native in-progress transition with the Action as branch owner." + }, + { + "id": "bexp-COPILOT04-C02", + "scenario": "For issue admission and start guidance, exercise the concrete boundary: The extension never creates, renames or deletes an Action-managed branch." + }, + { + "id": "bexp-COPILOT04-C03", + "scenario": "Opening issue admission and start guidance preserves the current native selection/input and requires the human's native confirmation; cancel performs no mutation." + }, + { + "id": "bexp-COPILOT04-C04", + "scenario": "A changed target, permission or selection while issue admission and start guidance is being prepared invalidates the handoff and refreshes its exact scope." + }, + { + "id": "bexp-COPILOT04-C05", + "scenario": "Keyboard-only use of issue admission and start guidance announces the exact native destination and effect, returns focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-COPILOT-05", + "family": "COPILOT", + "title": "Plan, clarify and estimate requests", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported issue or PR conversation", + "userOutcome": "Prepare the selected plan, clarify or estimate command with explicit request text and context.", + "boundaryAcceptance": "A read-oriented command's possible agent cost is shown before human submission.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT05-C01", + "scenario": "Given the eligible supported issue or pr conversation and verified input, choosing plan, clarify and estimate requests produces this observable result: Prepare the selected plan, clarify or estimate command with explicit request text and context." + }, + { + "id": "bexp-COPILOT05-C02", + "scenario": "For plan, clarify and estimate requests, exercise the concrete boundary: A read-oriented command's possible agent cost is shown before human submission." + }, + { + "id": "bexp-COPILOT05-C03", + "scenario": "Plan, clarify and estimate requests with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT05-C04", + "scenario": "A changed target or revoked capability before plan, clarify and estimate requests prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT05-C05", + "scenario": "Keyboard-only use of plan, clarify and estimate requests announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-06", + "family": "COPILOT", + "title": "Explain, diagnose and test-plan requests", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported issue or PR conversation", + "userOutcome": "Prepare explain, diagnose or test-plan for the user's selected bounded context.", + "boundaryAcceptance": "Selected private code is not transmitted until the user explicitly includes and submits it.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT06-C01", + "scenario": "Given the eligible supported issue or pr conversation and verified input, choosing explain, diagnose and test-plan requests produces this observable result: Prepare explain, diagnose or test-plan for the user's selected bounded context." + }, + { + "id": "bexp-COPILOT06-C02", + "scenario": "For explain, diagnose and test-plan requests, exercise the concrete boundary: Selected private code is not transmitted until the user explicitly includes and submits it." + }, + { + "id": "bexp-COPILOT06-C03", + "scenario": "Explain, diagnose and test-plan requests with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT06-C04", + "scenario": "A changed target or revoked capability before explain, diagnose and test-plan requests prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT06-C05", + "scenario": "Keyboard-only use of explain, diagnose and test-plan requests announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-07", + "family": "COPILOT", + "title": "Analysis and review requests", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported conversations", + "userOutcome": "Prepare analyze, review, findings or recheck with the exact target and expected review effect.", + "boundaryAcceptance": "Findings reconciliation is not falsely described as always model-free.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT07-C01", + "scenario": "Given the eligible supported conversations and verified input, choosing analysis and review requests produces this observable result: Prepare analyze, review, findings or recheck with the exact target and expected review effect." + }, + { + "id": "bexp-COPILOT07-C02", + "scenario": "For analysis and review requests, exercise the concrete boundary: Findings reconciliation is not falsely described as always model-free." + }, + { + "id": "bexp-COPILOT07-C03", + "scenario": "Analysis and review requests with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT07-C04", + "scenario": "A changed target or revoked capability before analysis and review requests prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT07-C05", + "scenario": "Keyboard-only use of analysis and review requests announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-08", + "family": "COPILOT", + "title": "Finding state navigator", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request findings", + "userOutcome": "Show open, fixed, obsolete, dismissed, reopened, verification and unknown states with current coverage.", + "boundaryAcceptance": "A resolved native thread alone cannot prove a finding was fixed.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT08-C01", + "scenario": "Given the eligible pull request findings and verified input, choosing finding state navigator produces this observable result: Show open, fixed, obsolete, dismissed, reopened, verification and unknown states with current coverage." + }, + { + "id": "bexp-COPILOT08-C02", + "scenario": "For finding state navigator, exercise the concrete boundary: A resolved native thread alone cannot prove a finding was fixed." + }, + { + "id": "bexp-COPILOT08-C03", + "scenario": "A denied, truncated or expired source for finding state navigator shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT08-C04", + "scenario": "Changing the selected repository/account/revision while finding state navigator is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-09", + "family": "COPILOT", + "title": "Targeted finding corrections", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Authoritative PR review thread or verified branch-scoped route", + "userOutcome": "Prepare fix for explicit verified finding IDs and show the exact branch/revision that the Action will recheck.", + "boundaryAcceptance": "Unknown or foreign-fork write authority gives copy-only guidance instead of a guessed target.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT09-C01", + "scenario": "Given the eligible authoritative pr review thread or verified branch-scoped route and verified input, choosing targeted finding corrections produces this observable result: Prepare fix for explicit verified finding IDs and show the exact branch/revision that the Action will recheck." + }, + { + "id": "bexp-COPILOT09-C02", + "scenario": "For targeted finding corrections, exercise the concrete boundary: Unknown or foreign-fork write authority gives copy-only guidance instead of a guessed target." + }, + { + "id": "bexp-COPILOT09-C03", + "scenario": "Targeted finding corrections with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT09-C04", + "scenario": "A changed target or revoked capability before targeted finding corrections prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT09-C05", + "scenario": "Keyboard-only use of targeted finding corrections announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-10", + "family": "COPILOT", + "title": "Finding dismissal preparation", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported current finding context", + "userOutcome": "Prepare dismiss for selected current IDs with explicit rationale and scope.", + "boundaryAcceptance": "Dismissal remains a state-changing authorized request even though it changes no files.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT10-C01", + "scenario": "Given the eligible supported current finding context and verified input, choosing finding dismissal preparation produces this observable result: Prepare dismiss for selected current IDs with explicit rationale and scope." + }, + { + "id": "bexp-COPILOT10-C02", + "scenario": "For finding dismissal preparation, exercise the concrete boundary: Dismissal remains a state-changing authorized request even though it changes no files." + }, + { + "id": "bexp-COPILOT10-C03", + "scenario": "Finding dismissal preparation with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT10-C04", + "scenario": "A changed target or revoked capability before finding dismissal preparation prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT10-C05", + "scenario": "Keyboard-only use of finding dismissal preparation announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-11", + "family": "COPILOT", + "title": "Implementation requests", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported authoritative branch-scoped context", + "userOutcome": "Prepare a concrete implementation request with explicit scope, branch, revision and verification expectations.", + "boundaryAcceptance": "An issue-only context without an authoritative branch route cannot invent a write target.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT11-C01", + "scenario": "Given the eligible supported authoritative branch-scoped context and verified input, choosing implementation requests produces this observable result: Prepare a concrete implementation request with explicit scope, branch, revision and verification expectations." + }, + { + "id": "bexp-COPILOT11-C02", + "scenario": "For implementation requests, exercise the concrete boundary: An issue-only context without an authoritative branch route cannot invent a write target." + }, + { + "id": "bexp-COPILOT11-C03", + "scenario": "Implementation requests with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT11-C04", + "scenario": "A changed target or revoked capability before implementation requests prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT11-C05", + "scenario": "Keyboard-only use of implementation requests announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-12", + "family": "COPILOT", + "title": "Learned rule preparation", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Verified current PR or native issue branch route", + "userOutcome": "Prepare remember with user-authored rule text, affected repository file and persistent-effect warning.", + "boundaryAcceptance": "Untrusted page instructions cannot become a persistent learned rule without explicit human review.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT12-C01", + "scenario": "Given the eligible verified current pr or native issue branch route and verified input, choosing learned rule preparation produces this observable result: Prepare remember with user-authored rule text, affected repository file and persistent-effect warning." + }, + { + "id": "bexp-COPILOT12-C02", + "scenario": "For learned rule preparation, exercise the concrete boundary: Untrusted page instructions cannot become a persistent learned rule without explicit human review." + }, + { + "id": "bexp-COPILOT12-C03", + "scenario": "Learned rule preparation with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT12-C04", + "scenario": "A changed target or revoked capability before learned rule preparation prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT12-C05", + "scenario": "Keyboard-only use of learned rule preparation announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-13", + "family": "COPILOT", + "title": "Branch synchronization workbench", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Verified issue or PR branch context", + "userOutcome": "Prepare sync-branch with reviewed dry-run, no-agent and optional verified source choices.", + "boundaryAcceptance": "The source is selected from authoritative refs and cannot be injected through page prose.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT13-C01", + "scenario": "Given the eligible verified issue or pr branch context and verified input, choosing branch synchronization workbench produces this observable result: Prepare sync-branch with reviewed dry-run, no-agent and optional verified source choices." + }, + { + "id": "bexp-COPILOT13-C02", + "scenario": "For branch synchronization workbench, exercise the concrete boundary: The source is selected from authoritative refs and cannot be injected through page prose." + }, + { + "id": "bexp-COPILOT13-C03", + "scenario": "Branch synchronization workbench with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT13-C04", + "scenario": "A changed target or revoked capability before branch synchronization workbench prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT13-C05", + "scenario": "Keyboard-only use of branch synchronization workbench announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-14", + "family": "COPILOT", + "title": "Runtime doctor and health", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Issue, PR and setup center", + "userOutcome": "Prepare doctor and distinguish credential presence, runtime readiness and actual execution evidence.", + "boundaryAcceptance": "A read-only doctor result cannot certify write permissions or runner authentication.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT14-C01", + "scenario": "Given the eligible issue, pr and setup center and verified input, choosing runtime doctor and health produces this observable result: Prepare doctor and distinguish credential presence, runtime readiness and actual execution evidence." + }, + { + "id": "bexp-COPILOT14-C02", + "scenario": "For runtime doctor and health, exercise the concrete boundary: A read-only doctor result cannot certify write permissions or runner authentication." + }, + { + "id": "bexp-COPILOT14-C03", + "scenario": "Runtime doctor and health with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT14-C04", + "scenario": "A changed target or revoked capability before runtime doctor and health prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT14-C05", + "scenario": "Keyboard-only use of runtime doctor and health announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-15", + "family": "COPILOT", + "title": "Request history and receipts", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported conversation", + "userOutcome": "Prepare history and navigate current supported request receipts with correlation and source identity.", + "boundaryAcceptance": "Missing receipts do not imply an empty history or a failed execution.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT15-C01", + "scenario": "Given the eligible supported conversation and verified input, choosing request history and receipts produces this observable result: Prepare history and navigate current supported request receipts with correlation and source identity." + }, + { + "id": "bexp-COPILOT15-C02", + "scenario": "For request history and receipts, exercise the concrete boundary: Missing receipts do not imply an empty history or a failed execution." + }, + { + "id": "bexp-COPILOT15-C03", + "scenario": "Request history and receipts with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT15-C04", + "scenario": "A changed target or revoked capability before request history and receipts prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT15-C05", + "scenario": "Keyboard-only use of request history and receipts announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-16", + "family": "COPILOT", + "title": "PR description and help", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Supported PR conversation", + "userOutcome": "Prepare description or help with the installed capability and potential PR-body effect explained.", + "boundaryAcceptance": "Description refresh cannot overwrite a native draft without an explicit operator decision.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT16-C01", + "scenario": "Given the eligible supported pr conversation and verified input, choosing pr description and help produces this observable result: Prepare description or help with the installed capability and potential PR-body effect explained." + }, + { + "id": "bexp-COPILOT16-C02", + "scenario": "For pr description and help, exercise the concrete boundary: Description refresh cannot overwrite a native draft without an explicit operator decision." + }, + { + "id": "bexp-COPILOT16-C03", + "scenario": "PR description and help with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-COPILOT16-C04", + "scenario": "A changed target or revoked capability before pr description and help prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-COPILOT16-C05", + "scenario": "Keyboard-only use of pr description and help announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-COPILOT-17", + "family": "COPILOT", + "title": "Approval and blocker explanation", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request status", + "userOutcome": "Explain current review, check, finding, policy and branch-sync blockers with source links.", + "boundaryAcceptance": "The extension never grants approval or converts unknown-producer checks into verified checks.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT17-C01", + "scenario": "Given the eligible pull request status and verified input, choosing approval and blocker explanation produces this observable result: Explain current review, check, finding, policy and branch-sync blockers with source links." + }, + { + "id": "bexp-COPILOT17-C02", + "scenario": "For approval and blocker explanation, exercise the concrete boundary: The extension never grants approval or converts unknown-producer checks into verified checks." + }, + { + "id": "bexp-COPILOT17-C03", + "scenario": "A denied, truncated or expired source for approval and blocker explanation shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT17-C04", + "scenario": "Changing the selected repository/account/revision while approval and blocker explanation is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-18", + "family": "COPILOT", + "title": "Queue and concurrency view", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Copilot runs and control center", + "userOutcome": "Show durable lifecycle, temporary activity and human waiting as independent facts.", + "boundaryAcceptance": "An old agent label cannot prove a current active run or permanently block a page feature.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT18-C01", + "scenario": "Given the eligible copilot runs and control center and verified input, choosing queue and concurrency view produces this observable result: Show durable lifecycle, temporary activity and human waiting as independent facts." + }, + { + "id": "bexp-COPILOT18-C02", + "scenario": "For queue and concurrency view, exercise the concrete boundary: An old agent label cannot prove a current active run or permanently block a page feature." + }, + { + "id": "bexp-COPILOT18-C03", + "scenario": "A denied, truncated or expired source for queue and concurrency view shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT18-C04", + "scenario": "Changing the selected repository/account/revision while queue and concurrency view is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-19", + "family": "COPILOT", + "title": "Release and hotfix launch guidance", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Installed release and hotfix issue forms", + "userOutcome": "Prepare the appropriate native form with version, origin and production-first consequences for human submission.", + "boundaryAcceptance": "The extension never silently creates a release issue or selects an unverified version tag.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT19-C01", + "scenario": "Given the eligible installed release and hotfix issue forms and verified input, choosing release and hotfix launch guidance produces this observable result: Prepare the appropriate native form with version, origin and production-first consequences for human submission." + }, + { + "id": "bexp-COPILOT19-C02", + "scenario": "For release and hotfix launch guidance, exercise the concrete boundary: The extension never silently creates a release issue or selects an unverified version tag." + }, + { + "id": "bexp-COPILOT19-C03", + "scenario": "Opening release and hotfix launch guidance preserves all existing native form answers and requires human native submission; cancel performs no mutation." + }, + { + "id": "bexp-COPILOT19-C04", + "scenario": "A changed installed form, target or required field while release and hotfix launch guidance is being prepared invalidates that preparation and preserves the existing native answers." + }, + { + "id": "bexp-COPILOT19-C05", + "scenario": "Keyboard-only use of release and hotfix launch guidance announces the exact form, target and effect, restores focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-COPILOT-20", + "family": "COPILOT", + "title": "Deployment review handoff", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Verified deployment control center", + "userOutcome": "Show publication state, intended deploy-label or native approval action, modes and retained effects before opening the exact native control.", + "boundaryAcceptance": "Unknown deployment policy blocks an asserted safe launch; page opening never deploys.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT20-C01", + "scenario": "Given the eligible verified deployment control center and verified input, choosing deployment review handoff produces this observable result: Show publication state, intended deploy-label or native approval action, modes and retained effects before opening the exact native control." + }, + { + "id": "bexp-COPILOT20-C02", + "scenario": "For deployment review handoff, exercise the concrete boundary: Unknown deployment policy blocks an asserted safe launch; page opening never deploys." + }, + { + "id": "bexp-COPILOT20-C03", + "scenario": "Opening deployment review handoff preserves the current native selection/input and requires the human's native confirmation; cancel performs no mutation." + }, + { + "id": "bexp-COPILOT20-C04", + "scenario": "A changed target, permission or selection while deployment review handoff is being prepared invalidates the handoff and refreshes its exact scope." + }, + { + "id": "bexp-COPILOT20-C05", + "scenario": "Keyboard-only use of deployment review handoff announces the exact native destination and effect, returns focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-COPILOT-21", + "family": "COPILOT", + "title": "Reconciliation and recovery view", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Deployment issue and promotion/reconciliation PRs", + "userOutcome": "Separate published artifacts, pending development targets, cleanup and permitted recovery operations.", + "boundaryAcceptance": "Immutable tags, unknown lineage and nonretryable blocks are never repaired by browser metadata edits.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT21-C01", + "scenario": "Given the eligible deployment issue and promotion/reconciliation prs and verified input, choosing reconciliation and recovery view produces this observable result: Separate published artifacts, pending development targets, cleanup and permitted recovery operations." + }, + { + "id": "bexp-COPILOT21-C02", + "scenario": "For reconciliation and recovery view, exercise the concrete boundary: Immutable tags, unknown lineage and nonretryable blocks are never repaired by browser metadata edits." + }, + { + "id": "bexp-COPILOT21-C03", + "scenario": "A denied, truncated or expired source for reconciliation and recovery view shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT21-C04", + "scenario": "Changing the selected repository/account/revision while reconciliation and recovery view is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-22", + "family": "COPILOT", + "title": "Policy and configuration provenance", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Copilot panel and settings", + "userOutcome": "Show versioned workflow/input/Variable scope and source-time policy limitations with exact links.", + "boundaryAcceptance": "Secret existence is presence only; hidden effective values remain unknown.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT22-C01", + "scenario": "Given the eligible copilot panel and settings and verified input, choosing policy and configuration provenance produces this observable result: Show versioned workflow/input/Variable scope and source-time policy limitations with exact links." + }, + { + "id": "bexp-COPILOT22-C02", + "scenario": "For policy and configuration provenance, exercise the concrete boundary: Secret existence is presence only; hidden effective values remain unknown." + }, + { + "id": "bexp-COPILOT22-C03", + "scenario": "A denied, truncated or expired source for policy and configuration provenance shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT22-C04", + "scenario": "Changing the selected repository/account/revision while policy and configuration provenance is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-23", + "family": "COPILOT", + "title": "Run, cost and evidence inspection", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Copilot history and job summaries", + "userOutcome": "Present published duration, usage/cost and verification artifacts only when the producer supplies them.", + "boundaryAcceptance": "Missing usage is unknown, never zero, and no billing value is inferred from a model name.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT23-C01", + "scenario": "Given the eligible copilot history and job summaries and verified input, choosing run, cost and evidence inspection produces this observable result: Present published duration, usage/cost and verification artifacts only when the producer supplies them." + }, + { + "id": "bexp-COPILOT23-C02", + "scenario": "For run, cost and evidence inspection, exercise the concrete boundary: Missing usage is unknown, never zero, and no billing value is inferred from a model name." + }, + { + "id": "bexp-COPILOT23-C03", + "scenario": "A denied, truncated or expired source for run, cost and evidence inspection shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT23-C04", + "scenario": "Changing the selected repository/account/revision while run, cost and evidence inspection is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-COPILOT-24", + "family": "COPILOT", + "title": "Capability and command compatibility", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Control center and every Copilot action", + "userOutcome": "Show the installed supported command/context matrix and explain unavailable product actions.", + "boundaryAcceptance": "An unknown Action version cannot receive a newly invented command syntax or event route.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-COPILOT" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-COPILOT24-C01", + "scenario": "Given the eligible control center and every copilot action and verified input, choosing capability and command compatibility produces this observable result: Show the installed supported command/context matrix and explain unavailable product actions." + }, + { + "id": "bexp-COPILOT24-C02", + "scenario": "For capability and command compatibility, exercise the concrete boundary: An unknown Action version cannot receive a newly invented command syntax or event route." + }, + { + "id": "bexp-COPILOT24-C03", + "scenario": "A denied, truncated or expired source for capability and command compatibility shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-COPILOT24-C04", + "scenario": "Changing the selected repository/account/revision while capability and command compatibility is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/ISSUE.v1.json b/specs/browser-extension/features/ISSUE.v1.json new file mode 100644 index 000000000..0329f277f --- /dev/null +++ b/specs/browser-extension/features/ISSUE.v1.json @@ -0,0 +1,646 @@ +{ + "id": "ISSUE", + "title": "Issues, discussions and collaboration", + "features": [ + { + "id": "BEX-ISSUE-01", + "family": "ISSUE", + "title": "Issue triage summary", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Issue header and lists", + "userOutcome": "Show observed state, ownership, labels, milestone and next human action without inferring priority.", + "boundaryAcceptance": "Denied metadata cannot be displayed as unassigned or unlabeled.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE01-C01", + "scenario": "Given the eligible issue header and lists and verified input, choosing issue triage summary produces this observable result: Show observed state, ownership, labels, milestone and next human action without inferring priority." + }, + { + "id": "bexp-ISSUE01-C02", + "scenario": "For issue triage summary, exercise the concrete boundary: Denied metadata cannot be displayed as unassigned or unlabeled." + }, + { + "id": "bexp-ISSUE01-C03", + "scenario": "A denied, truncated or expired source for issue triage summary shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-ISSUE01-C04", + "scenario": "Changing the selected repository/account/revision while issue triage summary is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-02", + "family": "ISSUE", + "title": "Structured issue drafting", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Native issue forms", + "userOutcome": "Prepare an installed issue form with explicit user answers and validation hints.", + "boundaryAcceptance": "The extension does not silently replace an enabled form with a blank issue or submit it.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE02-C01", + "scenario": "Given the eligible native issue forms and verified input, choosing structured issue drafting produces this observable result: Prepare an installed issue form with explicit user answers and validation hints." + }, + { + "id": "bexp-ISSUE02-C02", + "scenario": "For structured issue drafting, exercise the concrete boundary: The extension does not silently replace an enabled form with a blank issue or submit it." + }, + { + "id": "bexp-ISSUE02-C03", + "scenario": "Opening structured issue drafting preserves all existing native form answers and requires human native submission; cancel performs no mutation." + }, + { + "id": "bexp-ISSUE02-C04", + "scenario": "A changed installed form, target or required field while structured issue drafting is being prepared invalidates that preparation and preserves the existing native answers." + }, + { + "id": "bexp-ISSUE02-C05", + "scenario": "Keyboard-only use of structured issue drafting announces the exact form, target and effect, restores focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-ISSUE-03", + "family": "ISSUE", + "title": "Related issue and PR navigation", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Issue and PR sidebars", + "userOutcome": "Show native parent, sub-issue, dependency and closing-PR relationships when available.", + "boundaryAcceptance": "Textual mentions remain suggestions until the canonical relationship is verified.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE03-C01", + "scenario": "Given the eligible issue and pr sidebars and verified input, choosing related issue and pr navigation produces this observable result: Show native parent, sub-issue, dependency and closing-PR relationships when available." + }, + { + "id": "bexp-ISSUE03-C02", + "scenario": "For related issue and pr navigation, exercise the concrete boundary: Textual mentions remain suggestions until the canonical relationship is verified." + }, + { + "id": "bexp-ISSUE03-C03", + "scenario": "A denied, truncated or expired source for related issue and pr navigation shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-ISSUE03-C04", + "scenario": "Changing the selected repository/account/revision while related issue and pr navigation is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-04", + "family": "ISSUE", + "title": "Label and assignee adjustments", + "delivery": "required-for-product-acceptance", + "mode": "write", + "surface": "Issue and PR triage controls", + "userOutcome": "Preview and apply one explicit add/remove label or assignee change with current scope and read-back.", + "boundaryAcceptance": "Conflicting changes, missing write access and protected lifecycle labels route to native or Action-owned controls.", + "permissionProfile": "explicit-user-write", + "dataSource": "canonical target, separately authorized write identity and reviewed intent", + "freshnessRule": "final live target/permission/approval fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE04-C01", + "scenario": "Given the eligible issue and pr triage controls and verified input, choosing label and assignee adjustments produces this observable result: Preview and apply one explicit add/remove label or assignee change with current scope and read-back." + }, + { + "id": "bexp-ISSUE04-C02", + "scenario": "For label and assignee adjustments, exercise the concrete boundary: Conflicting changes, missing write access and protected lifecycle labels route to native or Action-owned controls." + }, + { + "id": "bexp-ISSUE04-C03", + "scenario": "Opening or refreshing label and assignee adjustments performs no write; a denied write grant leaves the repository unchanged." + }, + { + "id": "bexp-ISSUE04-C04", + "scenario": "A changed target/head/current value after the preview for label and assignee adjustments invalidates approval and requires review again." + }, + { + "id": "bexp-ISSUE04-C05", + "scenario": "A timeout after submitting label and assignee adjustments is reconciled through canonical state and is never retried blindly." + }, + { + "id": "bexp-ISSUE04-C06", + "scenario": "A duplicate click or restored tab for label and assignee adjustments cannot reuse a consumed operation intent." + }, + { + "id": "bexp-ISSUE04-C07", + "scenario": "After the provider acknowledges one label/assignee change, a denied read-back leaves that exact target acknowledged but verification unavailable; the UI cannot claim verified success, invent per-item failures or issue an automatic rollback." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-05", + "family": "ISSUE", + "title": "Milestone and project handoff", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Issue and PR sidebars", + "userOutcome": "Open a verified milestone or project destination and prepare the selected native adjustment.", + "boundaryAcceptance": "Unavailable Projects access does not trigger broader credential fallback.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE05-C01", + "scenario": "Given the eligible issue and pr sidebars and verified input, choosing milestone and project handoff produces this observable result: Open a verified milestone or project destination and prepare the selected native adjustment." + }, + { + "id": "bexp-ISSUE05-C02", + "scenario": "For milestone and project handoff, exercise the concrete boundary: Unavailable Projects access does not trigger broader credential fallback." + }, + { + "id": "bexp-ISSUE05-C03", + "scenario": "Opening milestone and project handoff preserves the current native selection/input and requires the human's native confirmation; cancel performs no mutation." + }, + { + "id": "bexp-ISSUE05-C04", + "scenario": "A changed target, permission or selection while milestone and project handoff is being prepared invalidates the handoff and refreshes its exact scope." + }, + { + "id": "bexp-ISSUE05-C05", + "scenario": "Keyboard-only use of milestone and project handoff announces the exact native destination and effect, returns focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-ISSUE-06", + "family": "ISSUE", + "title": "Duplicate and similarity research", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Issue search and triage", + "userOutcome": "Build explicit bounded searches from user-selected text and present source-linked candidate duplicates.", + "boundaryAcceptance": "Similarity is advisory and never closes or links an issue automatically.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE06-C01", + "scenario": "Given the eligible issue search and triage and verified input, choosing duplicate and similarity research produces this observable result: Build explicit bounded searches from user-selected text and present source-linked candidate duplicates." + }, + { + "id": "bexp-ISSUE06-C02", + "scenario": "For duplicate and similarity research, exercise the concrete boundary: Similarity is advisory and never closes or links an issue automatically." + }, + { + "id": "bexp-ISSUE06-C03", + "scenario": "A denied, truncated or expired source for duplicate and similarity research shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-ISSUE06-C04", + "scenario": "Changing the selected repository/account/revision while duplicate and similarity research is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-07", + "family": "ISSUE", + "title": "Conversation content navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Long issues and discussions", + "userOutcome": "Navigate headings, decisions and loaded code blocks with source anchors and readable summaries of structure.", + "boundaryAcceptance": "Structural navigation never claims an AI interpretation was reviewed by a maintainer.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE07-C01", + "scenario": "Given the eligible long issues and discussions and verified input, choosing conversation content navigation produces this observable result: Navigate headings, decisions and loaded code blocks with source anchors and readable summaries of structure." + }, + { + "id": "bexp-ISSUE07-C02", + "scenario": "For conversation content navigation, exercise the concrete boundary: Structural navigation never claims an AI interpretation was reviewed by a maintainer." + }, + { + "id": "bexp-ISSUE07-C03", + "scenario": "After conversation content navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-08", + "family": "ISSUE", + "title": "Personal issue annotations", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Issue and PR context", + "userOutcome": "Keep session-first personal notes and reminders with clear local/account ownership.", + "boundaryAcceptance": "Persistent local notes require explicit opt-in and are excluded from shared repository state.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE08-C01", + "scenario": "Given the eligible issue and pr context and verified input, choosing personal issue annotations produces this observable result: Keep session-first personal notes and reminders with clear local/account ownership." + }, + { + "id": "bexp-ISSUE08-C02", + "scenario": "For personal issue annotations, exercise the concrete boundary: Persistent local notes require explicit opt-in and are excluded from shared repository state." + }, + { + "id": "bexp-ISSUE08-C03", + "scenario": "An invalid or future-schema change to personal issue annotations preserves the previous complete settings revision." + }, + { + "id": "bexp-ISSUE08-C04", + "scenario": "Personal issue annotations survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-09", + "family": "ISSUE", + "title": "Cross-reference insertion", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Native editors", + "userOutcome": "Prepare canonical selected references as readable Markdown with a preview of the exact targets.", + "boundaryAcceptance": "Untrusted text cannot inject an extra bot command, mention or hidden marker.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE09-C01", + "scenario": "Given the eligible native editors and verified input, choosing cross-reference insertion produces this observable result: Prepare canonical selected references as readable Markdown with a preview of the exact targets." + }, + { + "id": "bexp-ISSUE09-C02", + "scenario": "For cross-reference insertion, exercise the concrete boundary: Untrusted text cannot inject an extra bot command, mention or hidden marker." + }, + { + "id": "bexp-ISSUE09-C03", + "scenario": "Cross-reference insertion with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-ISSUE09-C04", + "scenario": "A changed target or revoked capability before cross-reference insertion prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-ISSUE09-C05", + "scenario": "Keyboard-only use of cross-reference insertion announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-ISSUE-10", + "family": "ISSUE", + "title": "Selected bulk triage", + "delivery": "required-for-product-acceptance", + "mode": "write", + "surface": "Issue and PR lists", + "userOutcome": "Review an explicit bounded selection and per-item label/assignee changes, then execute with item receipts.", + "boundaryAcceptance": "Selection never extends to unloaded pages; partial success and uncertain items remain separate.", + "permissionProfile": "explicit-user-write", + "dataSource": "canonical target, separately authorized write identity and reviewed intent", + "freshnessRule": "final live target/permission/approval fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE10-C01", + "scenario": "Given the eligible issue and pr lists and verified input, choosing selected bulk triage produces this observable result: Review an explicit bounded selection and per-item label/assignee changes, then execute with item receipts." + }, + { + "id": "bexp-ISSUE10-C02", + "scenario": "For selected bulk triage, exercise the concrete boundary: Selection never extends to unloaded pages; partial success and uncertain items remain separate." + }, + { + "id": "bexp-ISSUE10-C03", + "scenario": "Opening or refreshing selected bulk triage performs no write; a denied write grant leaves the repository unchanged." + }, + { + "id": "bexp-ISSUE10-C04", + "scenario": "A changed target/head/current value after the preview for selected bulk triage invalidates approval and requires review again." + }, + { + "id": "bexp-ISSUE10-C05", + "scenario": "A timeout after submitting selected bulk triage is reconciled through canonical state and is never retried blindly." + }, + { + "id": "bexp-ISSUE10-C06", + "scenario": "A duplicate click or restored tab for selected bulk triage cannot reuse a consumed operation intent." + }, + { + "id": "bexp-ISSUE10-C07", + "scenario": "A partially completed selection for selected bulk triage separates verified effects, failed items and uncertain items with no automatic rollback." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-11", + "family": "ISSUE", + "title": "Discussion and answer navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "GitHub Discussions", + "userOutcome": "Navigate loaded answers, categories and accepted-answer anchors while leaving moderation native.", + "boundaryAcceptance": "An accepted answer is not inferred from reactions or comment ordering.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE11-C01", + "scenario": "Given the eligible github discussions and verified input, choosing discussion and answer navigation produces this observable result: Navigate loaded answers, categories and accepted-answer anchors while leaving moderation native." + }, + { + "id": "bexp-ISSUE11-C02", + "scenario": "For discussion and answer navigation, exercise the concrete boundary: An accepted answer is not inferred from reactions or comment ordering." + }, + { + "id": "bexp-ISSUE11-C03", + "scenario": "After discussion and answer navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-ISSUE-12", + "family": "ISSUE", + "title": "Issue activity and dependency views", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Issue overview", + "userOutcome": "Show source-linked dependency blockers and chronological milestones from available native evidence.", + "boundaryAcceptance": "Circular, incomplete or inaccessible relationships are represented explicitly.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-ISSUE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-ISSUE12-C01", + "scenario": "Given the eligible issue overview and verified input, choosing issue activity and dependency views produces this observable result: Show source-linked dependency blockers and chronological milestones from available native evidence." + }, + { + "id": "bexp-ISSUE12-C02", + "scenario": "For issue activity and dependency views, exercise the concrete boundary: Circular, incomplete or inaccessible relationships are represented explicitly." + }, + { + "id": "bexp-ISSUE12-C03", + "scenario": "A denied, truncated or expired source for issue activity and dependency views shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-ISSUE12-C04", + "scenario": "Changing the selected repository/account/revision while issue activity and dependency views is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/NAV.v1.json b/specs/browser-extension/features/NAV.v1.json new file mode 100644 index 000000000..678053362 --- /dev/null +++ b/specs/browser-extension/features/NAV.v1.json @@ -0,0 +1,584 @@ +{ + "id": "NAV", + "title": "Navigation and context", + "features": [ + { + "id": "BEX-NAV-01", + "family": "NAV", + "title": "Repository command palette", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Repository pages", + "userOutcome": "Open a searchable keyboard palette of native destinations, personal views and eligible Copilot tools.", + "boundaryAcceptance": "Unsupported destinations are absent and native keyboard shortcuts keep precedence.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV01-C01", + "scenario": "Given the eligible repository pages and verified input, choosing repository command palette produces this observable result: Open a searchable keyboard palette of native destinations, personal views and eligible Copilot tools." + }, + { + "id": "bexp-NAV01-C02", + "scenario": "For repository command palette, exercise the concrete boundary: Unsupported destinations are absent and native keyboard shortcuts keep precedence." + }, + { + "id": "bexp-NAV01-C03", + "scenario": "After repository command palette mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-02", + "family": "NAV", + "title": "Canonical object links", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Issues, pull requests and commits", + "userOutcome": "Copy the canonical URL with repository and object type preserved.", + "boundaryAcceptance": "A same-number issue or unverified redirect cannot replace the observed target.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV02-C01", + "scenario": "Given the eligible issues, pull requests and commits and verified input, choosing canonical object links produces this observable result: Copy the canonical URL with repository and object type preserved." + }, + { + "id": "bexp-NAV02-C02", + "scenario": "For canonical object links, exercise the concrete boundary: A same-number issue or unverified redirect cannot replace the observed target." + }, + { + "id": "bexp-NAV02-C03", + "scenario": "After canonical object links mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-03", + "family": "NAV", + "title": "Immutable line permalinks", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Files and diffs", + "userOutcome": "Copy an exact commit and selected line range, with a readable preview.", + "boundaryAcceptance": "A moving branch or missing immutable revision disables permalink creation.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV03-C01", + "scenario": "Given the eligible files and diffs and verified input, choosing immutable line permalinks produces this observable result: Copy an exact commit and selected line range, with a readable preview." + }, + { + "id": "bexp-NAV03-C02", + "scenario": "For immutable line permalinks, exercise the concrete boundary: A moving branch or missing immutable revision disables permalink creation." + }, + { + "id": "bexp-NAV03-C03", + "scenario": "After immutable line permalinks mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-04", + "family": "NAV", + "title": "Default branch and origin navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Repository, directory and fork pages", + "userOutcome": "Jump to the observed default branch or verified upstream repository without losing the relative path when it exists.", + "boundaryAcceptance": "Missing paths offer the repository root instead of an invented file.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV04-C01", + "scenario": "Given the eligible repository, directory and fork pages and verified input, choosing default branch and origin navigation produces this observable result: Jump to the observed default branch or verified upstream repository without losing the relative path when it exists." + }, + { + "id": "bexp-NAV04-C02", + "scenario": "For default branch and origin navigation, exercise the concrete boundary: Missing paths offer the repository root instead of an invented file." + }, + { + "id": "bexp-NAV04-C03", + "scenario": "After default branch and origin navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-05", + "family": "NAV", + "title": "Branch and tag switch context", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Files, branches and tags", + "userOutcome": "Compare the current ref with a selected verified ref and preview file availability before switching.", + "boundaryAcceptance": "A deleted ref or incomplete ref listing cannot become the default branch implicitly.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV05-C01", + "scenario": "Given the eligible files, branches and tags and verified input, choosing branch and tag switch context produces this observable result: Compare the current ref with a selected verified ref and preview file availability before switching." + }, + { + "id": "bexp-NAV05-C02", + "scenario": "For branch and tag switch context, exercise the concrete boundary: A deleted ref or incomplete ref listing cannot become the default branch implicitly." + }, + { + "id": "bexp-NAV05-C03", + "scenario": "A denied, truncated or expired source for branch and tag switch context shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-NAV05-C04", + "scenario": "Changing the selected repository/account/revision while branch and tag switch context is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-06", + "family": "NAV", + "title": "Compare direction controls", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Compare pages", + "userOutcome": "Swap known base and head with a preview that preserves explicit comparison semantics.", + "boundaryAcceptance": "Cross-repository and three-dot comparisons retain their original repository identities.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV06-C01", + "scenario": "Given the eligible compare pages and verified input, choosing compare direction controls produces this observable result: Swap known base and head with a preview that preserves explicit comparison semantics." + }, + { + "id": "bexp-NAV06-C02", + "scenario": "For compare direction controls, exercise the concrete boundary: Cross-repository and three-dot comparisons retain their original repository identities." + }, + { + "id": "bexp-NAV06-C03", + "scenario": "After compare direction controls mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-07", + "family": "NAV", + "title": "Issue, pull request and commit references", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Conversations and rendered text", + "userOutcome": "Make unambiguous observed object references navigable with accessible object-type labels.", + "boundaryAcceptance": "Code samples, ambiguous identifiers and untrusted external hosts remain untouched.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV07-C01", + "scenario": "Given the eligible conversations and rendered text and verified input, choosing issue, pull request and commit references produces this observable result: Make unambiguous observed object references navigable with accessible object-type labels." + }, + { + "id": "bexp-NAV07-C02", + "scenario": "For issue, pull request and commit references, exercise the concrete boundary: Code samples, ambiguous identifiers and untrusted external hosts remain untouched." + }, + { + "id": "bexp-NAV07-C03", + "scenario": "After issue, pull request and commit references mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-08", + "family": "NAV", + "title": "Contextual breadcrumbs", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Deep file, review and workflow pages", + "userOutcome": "Show compact breadcrumbs to repository, associated PR and source run only when verified.", + "boundaryAcceptance": "Unknown associations remain explicitly unknown rather than guessed from a branch name.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV08-C01", + "scenario": "Given the eligible deep file, review and workflow pages and verified input, choosing contextual breadcrumbs produces this observable result: Show compact breadcrumbs to repository, associated PR and source run only when verified." + }, + { + "id": "bexp-NAV08-C02", + "scenario": "For contextual breadcrumbs, exercise the concrete boundary: Unknown associations remain explicitly unknown rather than guessed from a branch name." + }, + { + "id": "bexp-NAV08-C03", + "scenario": "After contextual breadcrumbs mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-09", + "family": "NAV", + "title": "Copy names and paths", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Repository, file and ref headers", + "userOutcome": "Copy normalized repository name, ref, file path or qualified object identifier through explicit commands.", + "boundaryAcceptance": "Clipboard denial exposes selectable text and preserves user selection.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV09-C01", + "scenario": "Given the eligible repository, file and ref headers and verified input, choosing copy names and paths produces this observable result: Copy normalized repository name, ref, file path or qualified object identifier through explicit commands." + }, + { + "id": "bexp-NAV09-C02", + "scenario": "For copy names and paths, exercise the concrete boundary: Clipboard denial exposes selectable text and preserves user selection." + }, + { + "id": "bexp-NAV09-C03", + "scenario": "After copy names and paths mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-10", + "family": "NAV", + "title": "Context menus for selected references", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Selected GitHub links and text", + "userOutcome": "Offer opt-in browser context-menu actions for validated links, permalinks and opening the local control center.", + "boundaryAcceptance": "Unrecognized selections and protected login pages receive no extension action.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [ + "contextMenus" + ], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV10-C01", + "scenario": "Given the eligible selected github links and text and verified input, choosing context menus for selected references produces this observable result: Offer opt-in browser context-menu actions for validated links, permalinks and opening the local control center." + }, + { + "id": "bexp-NAV10-C02", + "scenario": "For context menus for selected references, exercise the concrete boundary: Unrecognized selections and protected login pages receive no extension action." + }, + { + "id": "bexp-NAV10-C03", + "scenario": "After context menus for selected references mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-11", + "family": "NAV", + "title": "Personal location bookmarks", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Repository and object pages", + "userOutcome": "Pin an exact location in a named personal workspace with visibility and account scope shown.", + "boundaryAcceptance": "Private locations default to session retention and are excluded from ordinary settings export.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV11-C01", + "scenario": "Given the eligible repository and object pages and verified input, choosing personal location bookmarks produces this observable result: Pin an exact location in a named personal workspace with visibility and account scope shown." + }, + { + "id": "bexp-NAV11-C02", + "scenario": "For personal location bookmarks, exercise the concrete boundary: Private locations default to session retention and are excluded from ordinary settings export." + }, + { + "id": "bexp-NAV11-C03", + "scenario": "An invalid or future-schema change to personal location bookmarks preserves the previous complete settings revision." + }, + { + "id": "bexp-NAV11-C04", + "scenario": "Personal location bookmarks survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NAV-12", + "family": "NAV", + "title": "Related object preview", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Issue, PR, commit and workflow links", + "userOutcome": "Show an opt-in bounded preview containing canonical identity, state and source time.", + "boundaryAcceptance": "Hover alone does not trigger unbounded reads and denied private previews reveal no cached title.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NAV" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NAV12-C01", + "scenario": "Given the eligible issue, pr, commit and workflow links and verified input, choosing related object preview produces this observable result: Show an opt-in bounded preview containing canonical identity, state and source time." + }, + { + "id": "bexp-NAV12-C02", + "scenario": "For related object preview, exercise the concrete boundary: Hover alone does not trigger unbounded reads and denied private previews reveal no cached title." + }, + { + "id": "bexp-NAV12-C03", + "scenario": "A denied, truncated or expired source for related object preview shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-NAV12-C04", + "scenario": "Changing the selected repository/account/revision while related object preview is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/NOTIFY.v1.json b/specs/browser-extension/features/NOTIFY.v1.json new file mode 100644 index 000000000..eaedc010e --- /dev/null +++ b/specs/browser-extension/features/NOTIFY.v1.json @@ -0,0 +1,417 @@ +{ + "id": "NOTIFY", + "title": "Notifications and attention", + "features": [ + { + "id": "BEX-NOTIFY-01", + "family": "NOTIFY", + "title": "Loaded inbox grouping", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Native notifications page", + "userOutcome": "Group visible notifications by repository, reason and object type without API credentials.", + "boundaryAcceptance": "The group count is explicitly limited to loaded notifications.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY01-C01", + "scenario": "Given the eligible native notifications page and verified input, choosing loaded inbox grouping produces this observable result: Group visible notifications by repository, reason and object type without API credentials." + }, + { + "id": "bexp-NOTIFY01-C02", + "scenario": "For loaded inbox grouping, exercise the concrete boundary: The group count is explicitly limited to loaded notifications." + }, + { + "id": "bexp-NOTIFY01-C03", + "scenario": "After loaded inbox grouping mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NOTIFY-02", + "family": "NOTIFY", + "title": "Notification source previews", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Native notifications list", + "userOutcome": "Show observed source state and source links beside the native notification entry.", + "boundaryAcceptance": "Private content absent from the current page is not fetched with a classic token fallback.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY02-C01", + "scenario": "Given the eligible native notifications list and verified input, choosing notification source previews produces this observable result: Show observed source state and source links beside the native notification entry." + }, + { + "id": "bexp-NOTIFY02-C02", + "scenario": "For notification source previews, exercise the concrete boundary: Private content absent from the current page is not fetched with a classic token fallback." + }, + { + "id": "bexp-NOTIFY02-C03", + "scenario": "After notification source previews mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NOTIFY-03", + "family": "NOTIFY", + "title": "Explicit notification selection", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Native notifications page", + "userOutcome": "Select loaded notifications by visible reason/state and preview the exact set before native actions.", + "boundaryAcceptance": "Selection never includes unloaded notifications or executes a destructive action on page open.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY03-C01", + "scenario": "Given the eligible native notifications page and verified input, choosing explicit notification selection produces this observable result: Select loaded notifications by visible reason/state and preview the exact set before native actions." + }, + { + "id": "bexp-NOTIFY03-C02", + "scenario": "For explicit notification selection, exercise the concrete boundary: Selection never includes unloaded notifications or executes a destructive action on page open." + }, + { + "id": "bexp-NOTIFY03-C03", + "scenario": "After explicit notification selection mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NOTIFY-04", + "family": "NOTIFY", + "title": "Mark-read and unsubscribe handoff", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Native notification controls", + "userOutcome": "Focus the native mark-read, done or unsubscribe action for the reviewed selection.", + "boundaryAcceptance": "The official notification API's classic-token requirement never silently broadens access.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY04-C01", + "scenario": "Given the eligible native notification controls and verified input, choosing mark-read and unsubscribe handoff produces this observable result: Focus the native mark-read, done or unsubscribe action for the reviewed selection." + }, + { + "id": "bexp-NOTIFY04-C02", + "scenario": "For mark-read and unsubscribe handoff, exercise the concrete boundary: The official notification API's classic-token requirement never silently broadens access." + }, + { + "id": "bexp-NOTIFY04-C03", + "scenario": "Opening mark-read and unsubscribe handoff preserves the current native selection/input and requires the human's native confirmation; cancel performs no mutation." + }, + { + "id": "bexp-NOTIFY04-C04", + "scenario": "A changed target, permission or selection while mark-read and unsubscribe handoff is being prepared invalidates the handoff and refreshes its exact scope." + }, + { + "id": "bexp-NOTIFY04-C05", + "scenario": "Keyboard-only use of mark-read and unsubscribe handoff announces the exact native destination and effect, returns focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-NOTIFY-05", + "family": "NOTIFY", + "title": "Personal snooze and reminders", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Workspace attention queue", + "userOutcome": "Snooze a personal reference until a chosen local time and show its local-only status.", + "boundaryAcceptance": "Snoozing does not change GitHub subscription or guarantee a background notification delivery time.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY05-C01", + "scenario": "Given the eligible workspace attention queue and verified input, choosing personal snooze and reminders produces this observable result: Snooze a personal reference until a chosen local time and show its local-only status." + }, + { + "id": "bexp-NOTIFY05-C02", + "scenario": "For personal snooze and reminders, exercise the concrete boundary: Snoozing does not change GitHub subscription or guarantee a background notification delivery time." + }, + { + "id": "bexp-NOTIFY05-C03", + "scenario": "An invalid or future-schema change to personal snooze and reminders preserves the previous complete settings revision." + }, + { + "id": "bexp-NOTIFY05-C04", + "scenario": "Personal snooze and reminders survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NOTIFY-06", + "family": "NOTIFY", + "title": "Optional attention alerts", + "delivery": "required-for-product-acceptance", + "mode": "monitor", + "surface": "Extension toolbar and local center; basic OS notifications on Chrome/Firefox only", + "userOutcome": "Enable bounded opt-in alerts for explicitly tracked verified transitions with quiet hours and deduplication.", + "boundaryAcceptance": "Safari uses the accessible toolbar/center channel without an unsupported notifications grant; denied channels, suspension and missing evidence never create repeated prompts or guessed alerts.", + "permissionProfile": "explicit-bounded-alert-monitor", + "dataSource": "at most five explicitly tracked canonical targets through the shared read scheduler", + "freshnessRule": "alarm revalidates account/target/source; no stale or unknown alert", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [ + "notifications", + "alarms" + ], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "explicit user gesture selects an available platform channel, enables the selected-target subscription and requests only supported optional grants; each alarm wake revalidates current eligibility, identity, grants and shared budgets before reads or alerts", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY06-C01", + "scenario": "After explicit supported-channel/monitor grants and target selection, a due browser alarm observes one verified tracked transition and emits one redacted attention item through that platform adapter within quiet-hour and request budgets." + }, + { + "id": "bexp-NOTIFY06-C02", + "scenario": "Safari omits OS notifications and their permission and delivers toolbar/center attention; Chrome/Firefox denial leaves the requested mode off until an explicit local-channel choice; suspension/restart never claims exact delivery or repeats prompts." + }, + { + "id": "bexp-NOTIFY06-C03", + "scenario": "Pausing the repository or revoking a grant before an alarm fires prevents all reads and notifications for that target." + }, + { + "id": "bexp-NOTIFY06-C04", + "scenario": "A duplicate alarm or worker restart cannot emit the same target/revision/transition alert twice; quiet hours defer or suppress according to the chosen policy." + }, + { + "id": "bexp-NOTIFY06-C05", + "scenario": "More due targets than the six-GET-per-wake or shared hourly budget permits are rotated/deferred without exceeding any account/repository ceiling." + }, + { + "id": "bexp-NOTIFY06-C06", + "scenario": "Changing or losing the selected session identity clears private queued alert evidence and requires explicit reconnect before private monitoring resumes." + }, + { + "id": "bexp-NOTIFY06-C07", + "scenario": "A stale, partial, foreign-target or unknown source never generates a success/blocker alert as though it were verified current evidence." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NOTIFY-07", + "family": "NOTIFY", + "title": "Mentions and review attention views", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Native inbox and visible lists", + "userOutcome": "Focus visible direct mentions and review requests while preserving access to all hidden categories.", + "boundaryAcceptance": "A matching string alone cannot classify a private team mention or authoritative review request.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY07-C01", + "scenario": "Given the eligible native inbox and visible lists and verified input, choosing mentions and review attention views produces this observable result: Focus visible direct mentions and review requests while preserving access to all hidden categories." + }, + { + "id": "bexp-NOTIFY07-C02", + "scenario": "For mentions and review attention views, exercise the concrete boundary: A matching string alone cannot classify a private team mention or authoritative review request." + }, + { + "id": "bexp-NOTIFY07-C03", + "scenario": "After mentions and review attention views mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-NOTIFY-08", + "family": "NOTIFY", + "title": "Notification privacy and lifecycle", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Control center privacy page", + "userOutcome": "Inspect and clear local attention state with retention, quiet-hours and account isolation controls.", + "boundaryAcceptance": "Disconnect removes private cached evidence while preserving explicitly authored nonsecret settings.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-NOTIFY" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-NOTIFY08-C01", + "scenario": "Given the eligible control center privacy page and verified input, choosing notification privacy and lifecycle produces this observable result: Inspect and clear local attention state with retention, quiet-hours and account isolation controls." + }, + { + "id": "bexp-NOTIFY08-C02", + "scenario": "For notification privacy and lifecycle, exercise the concrete boundary: Disconnect removes private cached evidence while preserving explicitly authored nonsecret settings." + }, + { + "id": "bexp-NOTIFY08-C03", + "scenario": "An invalid or future-schema change to notification privacy and lifecycle preserves the previous complete settings revision." + }, + { + "id": "bexp-NOTIFY08-C04", + "scenario": "Notification privacy and lifecycle survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/RELEASE.v1.json b/specs/browser-extension/features/RELEASE.v1.json new file mode 100644 index 000000000..198681a83 --- /dev/null +++ b/specs/browser-extension/features/RELEASE.v1.json @@ -0,0 +1,410 @@ +{ + "id": "RELEASE", + "title": "Releases, tags and repository changes", + "features": [ + { + "id": "BEX-RELEASE-01", + "family": "RELEASE", + "title": "Release and tag navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Merged PRs, tags and releases", + "userOutcome": "Navigate verified native release/tag destinations and preserve immutable source links.", + "boundaryAcceptance": "A merge date alone cannot associate a PR with a release.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE01-C01", + "scenario": "Given the eligible merged prs, tags and releases and verified input, choosing release and tag navigation produces this observable result: Navigate verified native release/tag destinations and preserve immutable source links." + }, + { + "id": "bexp-RELEASE01-C02", + "scenario": "For release and tag navigation, exercise the concrete boundary: A merge date alone cannot associate a PR with a release." + }, + { + "id": "bexp-RELEASE01-C03", + "scenario": "After release and tag navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-RELEASE-02", + "family": "RELEASE", + "title": "Release comparison builder", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Releases and compare pages", + "userOutcome": "Prepare comparisons between selected existing tags and disclose unavailable refs.", + "boundaryAcceptance": "A missing tag is not substituted with a similarly named branch.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE02-C01", + "scenario": "Given the eligible releases and compare pages and verified input, choosing release comparison builder produces this observable result: Prepare comparisons between selected existing tags and disclose unavailable refs." + }, + { + "id": "bexp-RELEASE02-C02", + "scenario": "For release comparison builder, exercise the concrete boundary: A missing tag is not substituted with a similarly named branch." + }, + { + "id": "bexp-RELEASE02-C03", + "scenario": "A denied, truncated or expired source for release comparison builder shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-RELEASE02-C04", + "scenario": "Changing the selected repository/account/revision while release comparison builder is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-RELEASE-03", + "family": "RELEASE", + "title": "Unreleased change inspection", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Repository overview", + "userOutcome": "Show a bounded comparison of the default branch and a selected verified release tag.", + "boundaryAcceptance": "The view labels its chosen baseline instead of claiming a universal latest-release definition.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE03-C01", + "scenario": "Given the eligible repository overview and verified input, choosing unreleased change inspection produces this observable result: Show a bounded comparison of the default branch and a selected verified release tag." + }, + { + "id": "bexp-RELEASE03-C02", + "scenario": "For unreleased change inspection, exercise the concrete boundary: The view labels its chosen baseline instead of claiming a universal latest-release definition." + }, + { + "id": "bexp-RELEASE03-C03", + "scenario": "A denied, truncated or expired source for unreleased change inspection shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-RELEASE03-C04", + "scenario": "Changing the selected repository/account/revision while unreleased change inspection is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-RELEASE-04", + "family": "RELEASE", + "title": "Changelog drafting", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Native release editor", + "userOutcome": "Prepare user-reviewed Markdown from explicitly selected linked PRs and commits with source attribution.", + "boundaryAcceptance": "The extension does not publish a release or claim every change was collected.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE04-C01", + "scenario": "Given the eligible native release editor and verified input, choosing changelog drafting produces this observable result: Prepare user-reviewed Markdown from explicitly selected linked PRs and commits with source attribution." + }, + { + "id": "bexp-RELEASE04-C02", + "scenario": "For changelog drafting, exercise the concrete boundary: The extension does not publish a release or claim every change was collected." + }, + { + "id": "bexp-RELEASE04-C03", + "scenario": "Changelog drafting with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-RELEASE04-C04", + "scenario": "A changed target or revoked capability before changelog drafting prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-RELEASE04-C05", + "scenario": "Keyboard-only use of changelog drafting announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-RELEASE-05", + "family": "RELEASE", + "title": "Release asset verification context", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Release assets", + "userOutcome": "Show published checksums/signature/provenance links that actually exist for the selected asset.", + "boundaryAcceptance": "A checksum without an authenticated source is not labeled as a trusted signature.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE05-C01", + "scenario": "Given the eligible release assets and verified input, choosing release asset verification context produces this observable result: Show published checksums/signature/provenance links that actually exist for the selected asset." + }, + { + "id": "bexp-RELEASE05-C02", + "scenario": "For release asset verification context, exercise the concrete boundary: A checksum without an authenticated source is not labeled as a trusted signature." + }, + { + "id": "bexp-RELEASE05-C03", + "scenario": "A denied, truncated or expired source for release asset verification context shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-RELEASE05-C04", + "scenario": "Changing the selected repository/account/revision while release asset verification context is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-RELEASE-06", + "family": "RELEASE", + "title": "Dependency and security navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Dependency and security pages", + "userOutcome": "Link native dependency, advisory and update surfaces with available permissions shown.", + "boundaryAcceptance": "Private security alerts are not scraped from unrelated pages or exported by default.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE06-C01", + "scenario": "Given the eligible dependency and security pages and verified input, choosing dependency and security navigation produces this observable result: Link native dependency, advisory and update surfaces with available permissions shown." + }, + { + "id": "bexp-RELEASE06-C02", + "scenario": "For dependency and security navigation, exercise the concrete boundary: Private security alerts are not scraped from unrelated pages or exported by default." + }, + { + "id": "bexp-RELEASE06-C03", + "scenario": "After dependency and security navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-RELEASE-07", + "family": "RELEASE", + "title": "Branch comparison workspace", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Branches and compare pages", + "userOutcome": "Compare explicitly selected branches with ahead/behind and ancestry facts from canonical data.", + "boundaryAcceptance": "Divergence is not described as safely deletable or automatically reconcilable.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE07-C01", + "scenario": "Given the eligible branches and compare pages and verified input, choosing branch comparison workspace produces this observable result: Compare explicitly selected branches with ahead/behind and ancestry facts from canonical data." + }, + { + "id": "bexp-RELEASE07-C02", + "scenario": "For branch comparison workspace, exercise the concrete boundary: Divergence is not described as safely deletable or automatically reconcilable." + }, + { + "id": "bexp-RELEASE07-C03", + "scenario": "A denied, truncated or expired source for branch comparison workspace shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-RELEASE07-C04", + "scenario": "Changing the selected repository/account/revision while branch comparison workspace is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-RELEASE-08", + "family": "RELEASE", + "title": "Release activity attention", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Workspace release views", + "userOutcome": "Track selected release or tag links through explicit foreground refresh and optional alerts.", + "boundaryAcceptance": "No background repository-wide polling or automatic package execution occurs.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-RELEASE" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-RELEASE08-C01", + "scenario": "Given the eligible workspace release views and verified input, choosing release activity attention produces this observable result: Track selected release or tag links through explicit foreground refresh and optional alerts." + }, + { + "id": "bexp-RELEASE08-C02", + "scenario": "For release activity attention, exercise the concrete boundary: No background repository-wide polling or automatic package execution occurs." + }, + { + "id": "bexp-RELEASE08-C03", + "scenario": "An invalid or future-schema change to release activity attention preserves the previous complete settings revision." + }, + { + "id": "bexp-RELEASE08-C04", + "scenario": "Release activity attention survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/REVIEW.v1.json b/specs/browser-extension/features/REVIEW.v1.json new file mode 100644 index 000000000..6db938993 --- /dev/null +++ b/specs/browser-extension/features/REVIEW.v1.json @@ -0,0 +1,716 @@ +{ + "id": "REVIEW", + "title": "Pull requests and reviews", + "features": [ + { + "id": "BEX-REVIEW-01", + "family": "REVIEW", + "title": "Review readiness overview", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request header", + "userOutcome": "Separate review requests, required checks, conflicts, queue state and Copilot assessment with source times.", + "boundaryAcceptance": "A successful advisory check cannot establish overall merge readiness.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW01-C01", + "scenario": "Given the eligible pull request header and verified input, choosing review readiness overview produces this observable result: Separate review requests, required checks, conflicts, queue state and Copilot assessment with source times." + }, + { + "id": "bexp-REVIEW01-C02", + "scenario": "For review readiness overview, exercise the concrete boundary: A successful advisory check cannot establish overall merge readiness." + }, + { + "id": "bexp-REVIEW01-C03", + "scenario": "A denied, truncated or expired source for review readiness overview shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW01-C04", + "scenario": "Changing the selected repository/account/revision while review readiness overview is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-02", + "family": "REVIEW", + "title": "Finding and comment navigator", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request conversation and diffs", + "userOutcome": "Navigate native comments and verified findings by file, severity, author and current state.", + "boundaryAcceptance": "Incomplete collection preserves unknown totals and historical findings stay labeled.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW02-C01", + "scenario": "Given the eligible pull request conversation and diffs and verified input, choosing finding and comment navigator produces this observable result: Navigate native comments and verified findings by file, severity, author and current state." + }, + { + "id": "bexp-REVIEW02-C02", + "scenario": "For finding and comment navigator, exercise the concrete boundary: Incomplete collection preserves unknown totals and historical findings stay labeled." + }, + { + "id": "bexp-REVIEW02-C03", + "scenario": "A denied, truncated or expired source for finding and comment navigator shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW02-C04", + "scenario": "Changing the selected repository/account/revision while finding and comment navigator is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-03", + "family": "REVIEW", + "title": "Resolved and outdated thread controls", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Review threads", + "userOutcome": "Expand, collapse and restore selected thread categories while preserving editors and focus.", + "boundaryAcceptance": "An active draft or unresolved required action cannot be silently hidden.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW03-C01", + "scenario": "Given the eligible review threads and verified input, choosing resolved and outdated thread controls produces this observable result: Expand, collapse and restore selected thread categories while preserving editors and focus." + }, + { + "id": "bexp-REVIEW03-C02", + "scenario": "For resolved and outdated thread controls, exercise the concrete boundary: An active draft or unresolved required action cannot be silently hidden." + }, + { + "id": "bexp-REVIEW03-C03", + "scenario": "After resolved and outdated thread controls mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-04", + "family": "REVIEW", + "title": "Conversation event focus", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Long issue and PR timelines", + "userOutcome": "Focus comments, state changes, reviews or bot activity with visible hidden-event counts.", + "boundaryAcceptance": "Filtered workflow failures remain discoverable through an explicit blocker indicator.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW04-C01", + "scenario": "Given the eligible long issue and pr timelines and verified input, choosing conversation event focus produces this observable result: Focus comments, state changes, reviews or bot activity with visible hidden-event counts." + }, + { + "id": "bexp-REVIEW04-C02", + "scenario": "For conversation event focus, exercise the concrete boundary: Filtered workflow failures remain discoverable through an explicit blocker indicator." + }, + { + "id": "bexp-REVIEW04-C03", + "scenario": "After conversation event focus mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-05", + "family": "REVIEW", + "title": "Draft preservation and snippets", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Native comment and review editors", + "userOutcome": "Use local user-authored snippets with placeholder preview, append/keep/cancel and optional session drafts.", + "boundaryAcceptance": "No draft is sent to an agent or overwritten by a background refresh.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW05-C01", + "scenario": "Given the eligible native comment and review editors and verified input, choosing draft preservation and snippets produces this observable result: Use local user-authored snippets with placeholder preview, append/keep/cancel and optional session drafts." + }, + { + "id": "bexp-REVIEW05-C02", + "scenario": "For draft preservation and snippets, exercise the concrete boundary: No draft is sent to an agent or overwritten by a background refresh." + }, + { + "id": "bexp-REVIEW05-C03", + "scenario": "An invalid or future-schema change to draft preservation and snippets preserves the previous complete settings revision." + }, + { + "id": "bexp-REVIEW05-C04", + "scenario": "Draft preservation and snippets survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-06", + "family": "REVIEW", + "title": "Changed-since-review navigation", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Updated pull requests", + "userOutcome": "Compare a verified reviewed revision with the current head and open native comparisons.", + "boundaryAcceptance": "Force-pushed or unavailable commits show an unresolvable range instead of an empty diff.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW06-C01", + "scenario": "Given the eligible updated pull requests and verified input, choosing changed-since-review navigation produces this observable result: Compare a verified reviewed revision with the current head and open native comparisons." + }, + { + "id": "bexp-REVIEW06-C02", + "scenario": "For changed-since-review navigation, exercise the concrete boundary: Force-pushed or unavailable commits show an unresolvable range instead of an empty diff." + }, + { + "id": "bexp-REVIEW06-C03", + "scenario": "A denied, truncated or expired source for changed-since-review navigation shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW06-C04", + "scenario": "Changing the selected repository/account/revision while changed-since-review navigation is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-07", + "family": "REVIEW", + "title": "Requested reviewer context", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request sidebar", + "userOutcome": "Explain requested versus submitted reviews and team-based requests from canonical facts.", + "boundaryAcceptance": "Team membership or reviewer presence cannot substitute for a current approval.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW07-C01", + "scenario": "Given the eligible pull request sidebar and verified input, choosing requested reviewer context produces this observable result: Explain requested versus submitted reviews and team-based requests from canonical facts." + }, + { + "id": "bexp-REVIEW07-C02", + "scenario": "For requested reviewer context, exercise the concrete boundary: Team membership or reviewer presence cannot substitute for a current approval." + }, + { + "id": "bexp-REVIEW07-C03", + "scenario": "A denied, truncated or expired source for requested reviewer context shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW07-C04", + "scenario": "Changing the selected repository/account/revision while requested reviewer context is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-08", + "family": "REVIEW", + "title": "Review submission preparation", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Pull request review composer", + "userOutcome": "Open the native review summary with selected comment, approve or request-changes intent for human review.", + "boundaryAcceptance": "The extension never submits an approval or bypasses current repository review policy.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW08-C01", + "scenario": "Given the eligible pull request review composer and verified input, choosing review submission preparation produces this observable result: Open the native review summary with selected comment, approve or request-changes intent for human review." + }, + { + "id": "bexp-REVIEW08-C02", + "scenario": "For review submission preparation, exercise the concrete boundary: The extension never submits an approval or bypasses current repository review policy." + }, + { + "id": "bexp-REVIEW08-C03", + "scenario": "Review submission preparation with a nonempty native draft offers append/keep/cancel and never submits or overwrites it automatically." + }, + { + "id": "bexp-REVIEW08-C04", + "scenario": "A changed target or revoked capability before review submission preparation prepares text cancels that preparation with a native source link." + }, + { + "id": "bexp-REVIEW08-C05", + "scenario": "Keyboard-only use of review submission preparation announces its exact destination/effect, preserves literal operands and returns focus after cancellation." + } + ], + "nativeTarget": "human-composer" + }, + { + "id": "BEX-REVIEW-09", + "family": "REVIEW", + "title": "Conflict explanation and recovery links", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Conflicting pull requests", + "userOutcome": "Show which native comparison or managed synchronization control can resolve the observed conflict.", + "boundaryAcceptance": "Unknown mergeability stays pending and no browser edit manufactures a managed branch.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW09-C01", + "scenario": "Given the eligible conflicting pull requests and verified input, choosing conflict explanation and recovery links produces this observable result: Show which native comparison or managed synchronization control can resolve the observed conflict." + }, + { + "id": "bexp-REVIEW09-C02", + "scenario": "For conflict explanation and recovery links, exercise the concrete boundary: Unknown mergeability stays pending and no browser edit manufactures a managed branch." + }, + { + "id": "bexp-REVIEW09-C03", + "scenario": "A denied, truncated or expired source for conflict explanation and recovery links shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW09-C04", + "scenario": "Changing the selected repository/account/revision while conflict explanation and recovery links is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-10", + "family": "REVIEW", + "title": "Merge and queue handoff", + "delivery": "required-for-product-acceptance", + "mode": "draft", + "surface": "Pull request merge controls", + "userOutcome": "Prepare a contextual handoff showing target, revision, merge method and queue/protection implications.", + "boundaryAcceptance": "Unknown policy or a moved head blocks a claimed safe merge and returns to native GitHub.", + "permissionProfile": "native-human-submission", + "dataSource": "verified target plus explicit user input", + "freshnessRule": "live target/context checked before preparing the native draft", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW10-C01", + "scenario": "Given the eligible pull request merge controls and verified input, choosing merge and queue handoff produces this observable result: Prepare a contextual handoff showing target, revision, merge method and queue/protection implications." + }, + { + "id": "bexp-REVIEW10-C02", + "scenario": "For merge and queue handoff, exercise the concrete boundary: Unknown policy or a moved head blocks a claimed safe merge and returns to native GitHub." + }, + { + "id": "bexp-REVIEW10-C03", + "scenario": "Opening merge and queue handoff preserves the current native selection/input and requires the human's native confirmation; cancel performs no mutation." + }, + { + "id": "bexp-REVIEW10-C04", + "scenario": "A changed target, permission or selection while merge and queue handoff is being prepared invalidates the handoff and refreshes its exact scope." + }, + { + "id": "bexp-REVIEW10-C05", + "scenario": "Keyboard-only use of merge and queue handoff announces the exact native destination and effect, returns focus on cancel and submits nothing from the extension." + } + ], + "nativeTarget": "control-handoff" + }, + { + "id": "BEX-REVIEW-11", + "family": "REVIEW", + "title": "Task and checklist navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Descriptions and conversations", + "userOutcome": "Index loaded checklist items and link back to their source without editing them.", + "boundaryAcceptance": "Unchecked or partially loaded lists cannot be reported as complete.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW11-C01", + "scenario": "Given the eligible descriptions and conversations and verified input, choosing task and checklist navigation produces this observable result: Index loaded checklist items and link back to their source without editing them." + }, + { + "id": "bexp-REVIEW11-C02", + "scenario": "For task and checklist navigation, exercise the concrete boundary: Unchecked or partially loaded lists cannot be reported as complete." + }, + { + "id": "bexp-REVIEW11-C03", + "scenario": "After task and checklist navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-12", + "family": "REVIEW", + "title": "Change summary by ownership", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request overview", + "userOutcome": "Group verified changed paths by directory and available CODEOWNERS evidence with completeness shown.", + "boundaryAcceptance": "Unparsed ownership rules remain unknown and never nominate an invented reviewer.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW12-C01", + "scenario": "Given the eligible pull request overview and verified input, choosing change summary by ownership produces this observable result: Group verified changed paths by directory and available CODEOWNERS evidence with completeness shown." + }, + { + "id": "bexp-REVIEW12-C02", + "scenario": "For change summary by ownership, exercise the concrete boundary: Unparsed ownership rules remain unknown and never nominate an invented reviewer." + }, + { + "id": "bexp-REVIEW12-C03", + "scenario": "A denied, truncated or expired source for change summary by ownership shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW12-C04", + "scenario": "Changing the selected repository/account/revision while change summary by ownership is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-13", + "family": "REVIEW", + "title": "Saved review filters", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Review conversations and Files changed", + "userOutcome": "Save personal author, state and path filters in a named profile with a visible active-filter summary.", + "boundaryAcceptance": "A shared URL or new account does not inherit another person's private review context.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW13-C01", + "scenario": "Given the eligible review conversations and files changed and verified input, choosing saved review filters produces this observable result: Save personal author, state and path filters in a named profile with a visible active-filter summary." + }, + { + "id": "bexp-REVIEW13-C02", + "scenario": "For saved review filters, exercise the concrete boundary: A shared URL or new account does not inherit another person's private review context." + }, + { + "id": "bexp-REVIEW13-C03", + "scenario": "An invalid or future-schema change to saved review filters preserves the previous complete settings revision." + }, + { + "id": "bexp-REVIEW13-C04", + "scenario": "Saved review filters survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-REVIEW-14", + "family": "REVIEW", + "title": "Review evidence export", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Pull request overview", + "userOutcome": "Export an explicitly selected redacted review receipt with exact revisions, sources and missing evidence.", + "boundaryAcceptance": "The export excludes tokens, private source text and unrelated review comments by default.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-REVIEW" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-REVIEW14-C01", + "scenario": "Given the eligible pull request overview and verified input, choosing review evidence export produces this observable result: Export an explicitly selected redacted review receipt with exact revisions, sources and missing evidence." + }, + { + "id": "bexp-REVIEW14-C02", + "scenario": "For review evidence export, exercise the concrete boundary: The export excludes tokens, private source text and unrelated review comments by default." + }, + { + "id": "bexp-REVIEW14-C03", + "scenario": "A denied, truncated or expired source for review evidence export shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-REVIEW14-C04", + "scenario": "Changing the selected repository/account/revision while review evidence export is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/SEARCH.v1.json b/specs/browser-extension/features/SEARCH.v1.json new file mode 100644 index 000000000..963462304 --- /dev/null +++ b/specs/browser-extension/features/SEARCH.v1.json @@ -0,0 +1,402 @@ +{ + "id": "SEARCH", + "title": "Search and personal views", + "features": [ + { + "id": "BEX-SEARCH-01", + "family": "SEARCH", + "title": "Named saved searches", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "GitHub search and lists", + "userOutcome": "Save and restore an explicit query with host, account and repository scope.", + "boundaryAcceptance": "Opening a shared query never silently replaces it with a personal default.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH01-C01", + "scenario": "Given the eligible github search and lists and verified input, choosing named saved searches produces this observable result: Save and restore an explicit query with host, account and repository scope." + }, + { + "id": "bexp-SEARCH01-C02", + "scenario": "For named saved searches, exercise the concrete boundary: Opening a shared query never silently replaces it with a personal default." + }, + { + "id": "bexp-SEARCH01-C03", + "scenario": "An invalid or future-schema change to named saved searches preserves the previous complete settings revision." + }, + { + "id": "bexp-SEARCH01-C04", + "scenario": "Named saved searches survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-02", + "family": "SEARCH", + "title": "Search query builder", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Search controls", + "userOutcome": "Build supported native qualifiers through readable chips and preview the exact query.", + "boundaryAcceptance": "Unsupported qualifiers remain editable text and are not represented as validated filters.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH02-C01", + "scenario": "Given the eligible search controls and verified input, choosing search query builder produces this observable result: Build supported native qualifiers through readable chips and preview the exact query." + }, + { + "id": "bexp-SEARCH02-C02", + "scenario": "For search query builder, exercise the concrete boundary: Unsupported qualifiers remain editable text and are not represented as validated filters." + }, + { + "id": "bexp-SEARCH02-C03", + "scenario": "After search query builder mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-03", + "family": "SEARCH", + "title": "In-page loaded-result filtering", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Search and repository lists", + "userOutcome": "Filter already loaded results by visible properties with local-versus-server scope explained.", + "boundaryAcceptance": "Local filtering cannot claim it searched unseen pages.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH03-C01", + "scenario": "Given the eligible search and repository lists and verified input, choosing in-page loaded-result filtering produces this observable result: Filter already loaded results by visible properties with local-versus-server scope explained." + }, + { + "id": "bexp-SEARCH03-C02", + "scenario": "For in-page loaded-result filtering, exercise the concrete boundary: Local filtering cannot claim it searched unseen pages." + }, + { + "id": "bexp-SEARCH03-C03", + "scenario": "After in-page loaded-result filtering mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-04", + "family": "SEARCH", + "title": "Cross-repository work searches", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Local workspace", + "userOutcome": "Run explicit bounded saved searches across selected repositories with per-repository completeness.", + "boundaryAcceptance": "Denied repositories stay unavailable instead of disappearing from the result summary.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH04-C01", + "scenario": "Given the eligible local workspace and verified input, choosing cross-repository work searches produces this observable result: Run explicit bounded saved searches across selected repositories with per-repository completeness." + }, + { + "id": "bexp-SEARCH04-C02", + "scenario": "For cross-repository work searches, exercise the concrete boundary: Denied repositories stay unavailable instead of disappearing from the result summary." + }, + { + "id": "bexp-SEARCH04-C03", + "scenario": "A denied, truncated or expired source for cross-repository work searches shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-SEARCH04-C04", + "scenario": "Changing the selected repository/account/revision while cross-repository work searches is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-05", + "family": "SEARCH", + "title": "Result provenance and completeness", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Search results", + "userOutcome": "Show repository/object identity, observation time and pagination/truncation alongside result counts.", + "boundaryAcceptance": "An exhausted budget cannot be shown as a complete zero-result search.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH05-C01", + "scenario": "Given the eligible search results and verified input, choosing result provenance and completeness produces this observable result: Show repository/object identity, observation time and pagination/truncation alongside result counts." + }, + { + "id": "bexp-SEARCH05-C02", + "scenario": "For result provenance and completeness, exercise the concrete boundary: An exhausted budget cannot be shown as a complete zero-result search." + }, + { + "id": "bexp-SEARCH05-C03", + "scenario": "A denied, truncated or expired source for result provenance and completeness shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-SEARCH05-C04", + "scenario": "Changing the selected repository/account/revision while result provenance and completeness is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-06", + "family": "SEARCH", + "title": "Recent local navigation", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Control center and command palette", + "userOutcome": "Offer opt-in extension-local recent destinations with bounded retention and clear/delete controls.", + "boundaryAcceptance": "No browser history permission or background browsing-history collection is used.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH06-C01", + "scenario": "Given the eligible control center and command palette and verified input, choosing recent local navigation produces this observable result: Offer opt-in extension-local recent destinations with bounded retention and clear/delete controls." + }, + { + "id": "bexp-SEARCH06-C02", + "scenario": "For recent local navigation, exercise the concrete boundary: No browser history permission or background browsing-history collection is used." + }, + { + "id": "bexp-SEARCH06-C03", + "scenario": "An invalid or future-schema change to recent local navigation preserves the previous complete settings revision." + }, + { + "id": "bexp-SEARCH06-C04", + "scenario": "Recent local navigation survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-07", + "family": "SEARCH", + "title": "Search-to-workspace collections", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Search results", + "userOutcome": "Pin selected canonical results to an account-scoped personal collection with explicit privacy choice.", + "boundaryAcceptance": "Unloaded results and private titles are not copied into persistent collections implicitly.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH07-C01", + "scenario": "Given the eligible search results and verified input, choosing search-to-workspace collections produces this observable result: Pin selected canonical results to an account-scoped personal collection with explicit privacy choice." + }, + { + "id": "bexp-SEARCH07-C02", + "scenario": "For search-to-workspace collections, exercise the concrete boundary: Unloaded results and private titles are not copied into persistent collections implicitly." + }, + { + "id": "bexp-SEARCH07-C03", + "scenario": "An invalid or future-schema change to search-to-workspace collections preserves the previous complete settings revision." + }, + { + "id": "bexp-SEARCH07-C04", + "scenario": "Search-to-workspace collections survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SEARCH-08", + "family": "SEARCH", + "title": "Accessible result traversal", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Search and lists", + "userOutcome": "Move among visible results with stable focus, position announcements and return links.", + "boundaryAcceptance": "Native text input and browser find retain their normal keyboard behavior.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SEARCH" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SEARCH08-C01", + "scenario": "Given the eligible search and lists and verified input, choosing accessible result traversal produces this observable result: Move among visible results with stable focus, position announcements and return links." + }, + { + "id": "bexp-SEARCH08-C02", + "scenario": "For accessible result traversal, exercise the concrete boundary: Native text input and browser find retain their normal keyboard behavior." + }, + { + "id": "bexp-SEARCH08-C03", + "scenario": "After accessible result traversal mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/SETUP.v1.json b/specs/browser-extension/features/SETUP.v1.json new file mode 100644 index 000000000..01c349eb6 --- /dev/null +++ b/specs/browser-extension/features/SETUP.v1.json @@ -0,0 +1,1140 @@ +{ + "id": "SETUP", + "title": "Integrated Copilot setup and management", + "features": [ + { + "id": "BEX-SETUP-01", + "family": "SETUP", + "title": "Setup entry and repository confirmation", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Local setup route", + "userOutcome": "Confirm the exact repository and show inspect, configure, repair or full setup as separate journeys.", + "boundaryAcceptance": "A URL, local checkout and selected GitHub account mismatch blocks application.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP01-C01", + "scenario": "Given the eligible local setup route and verified input, choosing setup entry and repository confirmation produces this observable result: Confirm the exact repository and show inspect, configure, repair or full setup as separate journeys." + }, + { + "id": "bexp-SETUP01-C02", + "scenario": "For setup entry and repository confirmation, exercise the concrete boundary: A URL, local checkout and selected GitHub account mismatch blocks application." + }, + { + "id": "bexp-SETUP01-C03", + "scenario": "Setup entry and repository confirmation uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP01-C04", + "scenario": "A stale CLI controller or plan revision for setup entry and repository confirmation cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP01-C05", + "scenario": "Credentials and approval capabilities used during setup entry and repository confirmation never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP01-C06", + "scenario": "Cancellation or connection loss during setup entry and repository confirmation preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP01-C07", + "scenario": "An unavailable or incompatible local companion for setup entry and repository confirmation offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-02", + "family": "SETUP", + "title": "Shared full questionnaire", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Packaged setup wizard", + "userOutcome": "Use the shared setup questionnaire, catalog and validation for every existing CLI/web choice.", + "boundaryAcceptance": "Extension-only defaults cannot silently create a second setup policy.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP02-C01", + "scenario": "Given the eligible packaged setup wizard and verified input, choosing shared full questionnaire produces this observable result: Use the shared setup questionnaire, catalog and validation for every existing CLI/web choice." + }, + { + "id": "bexp-SETUP02-C02", + "scenario": "For shared full questionnaire, exercise the concrete boundary: Extension-only defaults cannot silently create a second setup policy." + }, + { + "id": "bexp-SETUP02-C03", + "scenario": "Shared full questionnaire uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP02-C04", + "scenario": "A stale CLI controller or plan revision for shared full questionnaire cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP02-C05", + "scenario": "Credentials and approval capabilities used during shared full questionnaire never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP02-C06", + "scenario": "Cancellation or connection loss during shared full questionnaire preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP02-C07", + "scenario": "An unavailable or incompatible local companion for shared full questionnaire offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-03", + "family": "SETUP", + "title": "Effective configuration inspector", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Copilot configuration route", + "userOutcome": "Inspect understood bindings, repository/organization precedence, source times and unknown values.", + "boundaryAcceptance": "A Secret name or complex workflow expression is not displayed as a verified effective value.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP03-C01", + "scenario": "Given the eligible copilot configuration route and verified input, choosing effective configuration inspector produces this observable result: Inspect understood bindings, repository/organization precedence, source times and unknown values." + }, + { + "id": "bexp-SETUP03-C02", + "scenario": "For effective configuration inspector, exercise the concrete boundary: A Secret name or complex workflow expression is not displayed as a verified effective value." + }, + { + "id": "bexp-SETUP03-C03", + "scenario": "Effective configuration inspector uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP03-C04", + "scenario": "A stale CLI controller or plan revision for effective configuration inspector cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP03-C05", + "scenario": "Credentials and approval capabilities used during effective configuration inspector never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP03-C06", + "scenario": "Cancellation or connection loss during effective configuration inspector preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP03-C07", + "scenario": "An unavailable or incompatible local companion for effective configuration inspector offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-04", + "family": "SETUP", + "title": "Focused runtime adjustments", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Configuration quick adjustments", + "userOutcome": "Review current/new value and existing scope, then delegate the existing narrow approved adjustment transaction.", + "boundaryAcceptance": "Structural changes, scope movement and unknown bindings require the full reviewed setup journey.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP04-C01", + "scenario": "Given the eligible configuration quick adjustments and verified input, choosing focused runtime adjustments produces this observable result: Review current/new value and existing scope, then delegate the existing narrow approved adjustment transaction." + }, + { + "id": "bexp-SETUP04-C02", + "scenario": "For focused runtime adjustments, exercise the concrete boundary: Structural changes, scope movement and unknown bindings require the full reviewed setup journey." + }, + { + "id": "bexp-SETUP04-C03", + "scenario": "Focused runtime adjustments uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP04-C04", + "scenario": "A stale CLI controller or plan revision for focused runtime adjustments cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP04-C05", + "scenario": "Credentials and approval capabilities used during focused runtime adjustments never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP04-C06", + "scenario": "Cancellation or connection loss during focused runtime adjustments preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP04-C07", + "scenario": "An unavailable or incompatible local companion for focused runtime adjustments offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-05", + "family": "SETUP", + "title": "Runner and verification setup", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Setup runtime stage", + "userOutcome": "Plan supported runner profiles, required runtime versions and verification setup with ownership preserved.", + "boundaryAcceptance": "Generated starter files do not count as a working verification environment.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP05-C01", + "scenario": "Given the eligible setup runtime stage and verified input, choosing runner and verification setup produces this observable result: Plan supported runner profiles, required runtime versions and verification setup with ownership preserved." + }, + { + "id": "bexp-SETUP05-C02", + "scenario": "For runner and verification setup, exercise the concrete boundary: Generated starter files do not count as a working verification environment." + }, + { + "id": "bexp-SETUP05-C03", + "scenario": "Runner and verification setup uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP05-C04", + "scenario": "A stale CLI controller or plan revision for runner and verification setup cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP05-C05", + "scenario": "Credentials and approval capabilities used during runner and verification setup never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP05-C06", + "scenario": "Cancellation or connection loss during runner and verification setup preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP05-C07", + "scenario": "An unavailable or incompatible local companion for runner and verification setup offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-06", + "family": "SETUP", + "title": "Credential role guidance", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Protected credential handoff", + "userOutcome": "Explain operator, bot and provider credential roles and open the paired trusted local setup step.", + "boundaryAcceptance": "No setup/bot/provider secret enters content scripts, extension messages or extension storage.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP06-C01", + "scenario": "Given the eligible protected credential handoff and verified input, choosing credential role guidance produces this observable result: Explain operator, bot and provider credential roles and open the paired trusted local setup step." + }, + { + "id": "bexp-SETUP06-C02", + "scenario": "For credential role guidance, exercise the concrete boundary: No setup/bot/provider secret enters content scripts, extension messages or extension storage." + }, + { + "id": "bexp-SETUP06-C03", + "scenario": "Credential role guidance uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP06-C04", + "scenario": "A stale CLI controller or plan revision for credential role guidance cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP06-C05", + "scenario": "Credentials and approval capabilities used during credential role guidance never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP06-C06", + "scenario": "Cancellation or connection loss during credential role guidance preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP06-C07", + "scenario": "An unavailable or incompatible local companion for credential role guidance offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-07", + "family": "SETUP", + "title": "Permission audit progress", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Setup permission stage", + "userOutcome": "Show canonical metadata-only initial read and approved final write-probe progress from the shared engine.", + "boundaryAcceptance": "A write probe is a real temporary mutation and cleanup uncertainty remains a partial result.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP07-C01", + "scenario": "Given the eligible setup permission stage and verified input, choosing permission audit progress produces this observable result: Show canonical metadata-only initial read and approved final write-probe progress from the shared engine." + }, + { + "id": "bexp-SETUP07-C02", + "scenario": "For permission audit progress, exercise the concrete boundary: A write probe is a real temporary mutation and cleanup uncertainty remains a partial result." + }, + { + "id": "bexp-SETUP07-C03", + "scenario": "Permission audit progress uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP07-C04", + "scenario": "A stale CLI controller or plan revision for permission audit progress cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP07-C05", + "scenario": "Credentials and approval capabilities used during permission audit progress never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP07-C06", + "scenario": "Cancellation or connection loss during permission audit progress preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP07-C07", + "scenario": "An unavailable or incompatible local companion for permission audit progress offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-08", + "family": "SETUP", + "title": "Reviewed installation plan", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Setup review stage", + "userOutcome": "Show exact files/resources, scope, defaults, conflicts, changed facts and consequences before privileged approval.", + "boundaryAcceptance": "A changed plan or target invalidates prior approval and requires a new review.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP08-C01", + "scenario": "Given the eligible setup review stage and verified input, choosing reviewed installation plan produces this observable result: Show exact files/resources, scope, defaults, conflicts, changed facts and consequences before privileged approval." + }, + { + "id": "bexp-SETUP08-C02", + "scenario": "For reviewed installation plan, exercise the concrete boundary: A changed plan or target invalidates prior approval and requires a new review." + }, + { + "id": "bexp-SETUP08-C03", + "scenario": "Reviewed installation plan uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP08-C04", + "scenario": "A stale CLI controller or plan revision for reviewed installation plan cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP08-C05", + "scenario": "Credentials and approval capabilities used during reviewed installation plan never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP08-C06", + "scenario": "Cancellation or connection loss during reviewed installation plan preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP08-C07", + "scenario": "An unavailable or incompatible local companion for reviewed installation plan offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-09", + "family": "SETUP", + "title": "Presets and organization reuse", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Setup planning stage", + "userOutcome": "Select named reviewed presets and organization inheritance with per-repository differences displayed.", + "boundaryAcceptance": "A preset cannot carry credentials, grant permissions or overwrite unrelated workflow customization.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP09-C01", + "scenario": "Given the eligible setup planning stage and verified input, choosing presets and organization reuse produces this observable result: Select named reviewed presets and organization inheritance with per-repository differences displayed." + }, + { + "id": "bexp-SETUP09-C02", + "scenario": "For presets and organization reuse, exercise the concrete boundary: A preset cannot carry credentials, grant permissions or overwrite unrelated workflow customization." + }, + { + "id": "bexp-SETUP09-C03", + "scenario": "Presets and organization reuse uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP09-C04", + "scenario": "A stale CLI controller or plan revision for presets and organization reuse cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP09-C05", + "scenario": "Credentials and approval capabilities used during presets and organization reuse never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP09-C06", + "scenario": "Cancellation or connection loss during presets and organization reuse preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP09-C07", + "scenario": "An unavailable or incompatible local companion for presets and organization reuse offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-10", + "family": "SETUP", + "title": "Batch repository setup", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Batch selection and review", + "userOutcome": "Preview an explicit bounded repository set and exact per-item plans using the shared batch engine.", + "boundaryAcceptance": "One approval cannot silently include a newly discovered repository or changed per-item plan.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP10-C01", + "scenario": "Given the eligible batch selection and review and verified input, choosing batch repository setup produces this observable result: Preview an explicit bounded repository set and exact per-item plans using the shared batch engine." + }, + { + "id": "bexp-SETUP10-C02", + "scenario": "For batch repository setup, exercise the concrete boundary: One approval cannot silently include a newly discovered repository or changed per-item plan." + }, + { + "id": "bexp-SETUP10-C03", + "scenario": "Batch repository setup uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP10-C04", + "scenario": "A stale CLI controller or plan revision for batch repository setup cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP10-C05", + "scenario": "Credentials and approval capabilities used during batch repository setup never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP10-C06", + "scenario": "Cancellation or connection loss during batch repository setup preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP10-C07", + "scenario": "An unavailable or incompatible local companion for batch repository setup offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-11", + "family": "SETUP", + "title": "Protected application and progress", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Paired local setup authority", + "userOutcome": "Run Apply only through the CLI-owned current review/controller and stream redacted effects back to the center.", + "boundaryAcceptance": "The extension cannot invoke arbitrary shell commands, push managed refs or bypass final grant re-audit.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP11-C01", + "scenario": "Given the eligible paired local setup authority and verified input, choosing protected application and progress produces this observable result: Run Apply only through the CLI-owned current review/controller and stream redacted effects back to the center." + }, + { + "id": "bexp-SETUP11-C02", + "scenario": "For protected application and progress, exercise the concrete boundary: The extension cannot invoke arbitrary shell commands, push managed refs or bypass final grant re-audit." + }, + { + "id": "bexp-SETUP11-C03", + "scenario": "Protected application and progress uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP11-C04", + "scenario": "A stale CLI controller or plan revision for protected application and progress cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP11-C05", + "scenario": "Credentials and approval capabilities used during protected application and progress never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP11-C06", + "scenario": "Cancellation or connection loss during protected application and progress preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP11-C07", + "scenario": "An unavailable or incompatible local companion for protected application and progress offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-12", + "family": "SETUP", + "title": "Doctor and installation evidence", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Setup result and health route", + "userOutcome": "Separate file/resource application, metadata diagnosis, runner verification and live Action execution evidence.", + "boundaryAcceptance": "Installed Secret presence does not prove credential validity or deployment success.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP12-C01", + "scenario": "Given the eligible setup result and health route and verified input, choosing doctor and installation evidence produces this observable result: Separate file/resource application, metadata diagnosis, runner verification and live Action execution evidence." + }, + { + "id": "bexp-SETUP12-C02", + "scenario": "For doctor and installation evidence, exercise the concrete boundary: Installed Secret presence does not prove credential validity or deployment success." + }, + { + "id": "bexp-SETUP12-C03", + "scenario": "Doctor and installation evidence uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP12-C04", + "scenario": "A stale CLI controller or plan revision for doctor and installation evidence cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP12-C05", + "scenario": "Credentials and approval capabilities used during doctor and installation evidence never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP12-C06", + "scenario": "Cancellation or connection loss during doctor and installation evidence preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP12-C07", + "scenario": "An unavailable or incompatible local companion for doctor and installation evidence offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-13", + "family": "SETUP", + "title": "Drift, upgrade and maintenance plans", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Configuration maintenance route", + "userOutcome": "Compare the installed known manifest and current reviewed plan with safe preserve/replace decisions.", + "boundaryAcceptance": "Unknown consumer files and newer schemas are never deleted or downgraded automatically.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP13-C01", + "scenario": "Given the eligible configuration maintenance route and verified input, choosing drift, upgrade and maintenance plans produces this observable result: Compare the installed known manifest and current reviewed plan with safe preserve/replace decisions." + }, + { + "id": "bexp-SETUP13-C02", + "scenario": "For drift, upgrade and maintenance plans, exercise the concrete boundary: Unknown consumer files and newer schemas are never deleted or downgraded automatically." + }, + { + "id": "bexp-SETUP13-C03", + "scenario": "Drift, upgrade and maintenance plans uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP13-C04", + "scenario": "A stale CLI controller or plan revision for drift, upgrade and maintenance plans cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP13-C05", + "scenario": "Credentials and approval capabilities used during drift, upgrade and maintenance plans never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP13-C06", + "scenario": "Cancellation or connection loss during drift, upgrade and maintenance plans preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP13-C07", + "scenario": "An unavailable or incompatible local companion for drift, upgrade and maintenance plans offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-14", + "family": "SETUP", + "title": "Cancellation and partial recovery", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Active setup and recovery route", + "userOutcome": "Cancel before new effects, retain completed effects and expose exact cleanup/retry ownership.", + "boundaryAcceptance": "Cancellation cannot undo completed writes or suppress an unresolved cleanup journal.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP14-C01", + "scenario": "Given the eligible active setup and recovery route and verified input, choosing cancellation and partial recovery produces this observable result: Cancel before new effects, retain completed effects and expose exact cleanup/retry ownership." + }, + { + "id": "bexp-SETUP14-C02", + "scenario": "For cancellation and partial recovery, exercise the concrete boundary: Cancellation cannot undo completed writes or suppress an unresolved cleanup journal." + }, + { + "id": "bexp-SETUP14-C03", + "scenario": "Cancellation and partial recovery uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP14-C04", + "scenario": "A stale CLI controller or plan revision for cancellation and partial recovery cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP14-C05", + "scenario": "Credentials and approval capabilities used during cancellation and partial recovery never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP14-C06", + "scenario": "Cancellation or connection loss during cancellation and partial recovery preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP14-C07", + "scenario": "An unavailable or incompatible local companion for cancellation and partial recovery offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-15", + "family": "SETUP", + "title": "Offline intent preparation and handoff", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Local wizard without companion", + "userOutcome": "Prepare a nonsecret portable setup intent and import it into a later reviewed local setup session.", + "boundaryAcceptance": "An exported intent is never an approval or a trusted installation manifest.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP15-C01", + "scenario": "Given the eligible local wizard without companion and verified input, choosing offline intent preparation and handoff produces this observable result: Prepare a nonsecret portable setup intent and import it into a later reviewed local setup session." + }, + { + "id": "bexp-SETUP15-C02", + "scenario": "For offline intent preparation and handoff, exercise the concrete boundary: An exported intent is never an approval or a trusted installation manifest." + }, + { + "id": "bexp-SETUP15-C03", + "scenario": "Offline intent preparation and handoff uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP15-C04", + "scenario": "A stale CLI controller or plan revision for offline intent preparation and handoff cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP15-C05", + "scenario": "Credentials and approval capabilities used during offline intent preparation and handoff never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP15-C06", + "scenario": "Cancellation or connection loss during offline intent preparation and handoff preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP15-C07", + "scenario": "An unavailable or incompatible local companion for offline intent preparation and handoff offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-16", + "family": "SETUP", + "title": "CLI pairing and controller lifecycle", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Connect local companion", + "userOutcome": "Pair an explicitly launched local CLI session, bind repository/controller and show liveness/expiry.", + "boundaryAcceptance": "The extension never scans loopback ports or adopts a session from a page-supplied URL.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP16-C01", + "scenario": "Given the eligible connect local companion and verified input, choosing cli pairing and controller lifecycle produces this observable result: Pair an explicitly launched local CLI session, bind repository/controller and show liveness/expiry." + }, + { + "id": "bexp-SETUP16-C02", + "scenario": "For cli pairing and controller lifecycle, exercise the concrete boundary: The extension never scans loopback ports or adopts a session from a page-supplied URL." + }, + { + "id": "bexp-SETUP16-C03", + "scenario": "CLI pairing and controller lifecycle uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP16-C04", + "scenario": "A stale CLI controller or plan revision for cli pairing and controller lifecycle cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP16-C05", + "scenario": "Credentials and approval capabilities used during cli pairing and controller lifecycle never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP16-C06", + "scenario": "Cancellation or connection loss during cli pairing and controller lifecycle preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP16-C07", + "scenario": "An unavailable or incompatible local companion for cli pairing and controller lifecycle offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-17", + "family": "SETUP", + "title": "Plan revision and audit history", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Setup review and result", + "userOutcome": "Navigate redacted plan revisions and verified effects without reusing an old approval.", + "boundaryAcceptance": "A restored browser tab cannot regain controller authority after expiry or takeover.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP17-C01", + "scenario": "Given the eligible setup review and result and verified input, choosing plan revision and audit history produces this observable result: Navigate redacted plan revisions and verified effects without reusing an old approval." + }, + { + "id": "bexp-SETUP17-C02", + "scenario": "For plan revision and audit history, exercise the concrete boundary: A restored browser tab cannot regain controller authority after expiry or takeover." + }, + { + "id": "bexp-SETUP17-C03", + "scenario": "Plan revision and audit history uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP17-C04", + "scenario": "A stale CLI controller or plan revision for plan revision and audit history cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP17-C05", + "scenario": "Credentials and approval capabilities used during plan revision and audit history never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP17-C06", + "scenario": "Cancellation or connection loss during plan revision and audit history preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP17-C07", + "scenario": "An unavailable or incompatible local companion for plan revision and audit history offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-SETUP-18", + "family": "SETUP", + "title": "Shared setup parity and documentation", + "delivery": "required-for-product-acceptance", + "mode": "setup", + "surface": "Help and acceptance surfaces", + "userOutcome": "Use the same setting catalog, localized explanations, examples and acceptance fixtures across CLI, web and extension.", + "boundaryAcceptance": "Any transport-specific unsupported step is explicit and cannot be silently skipped to claim completion.", + "permissionProfile": "cli-owned-setup", + "dataSource": "shared setup contracts and paired CLI metadata-only views", + "freshnessRule": "CLI plan revision, controller and permission audit", + "default": "local-planning-available; pairing-and-apply-explicit", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-SETUP" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-SETUP18-C01", + "scenario": "Given the eligible help and acceptance surfaces and verified input, choosing shared setup parity and documentation produces this observable result: Use the same setting catalog, localized explanations, examples and acceptance fixtures across CLI, web and extension." + }, + { + "id": "bexp-SETUP18-C02", + "scenario": "For shared setup parity and documentation, exercise the concrete boundary: Any transport-specific unsupported step is explicit and cannot be silently skipped to claim completion." + }, + { + "id": "bexp-SETUP18-C03", + "scenario": "Shared setup parity and documentation uses the same canonical question/setting or transaction contract as CLI and local web setup; adapter-specific defaults cannot diverge." + }, + { + "id": "bexp-SETUP18-C04", + "scenario": "A stale CLI controller or plan revision for shared setup parity and documentation cannot approve or start a new effect." + }, + { + "id": "bexp-SETUP18-C05", + "scenario": "Credentials and approval capabilities used during shared setup parity and documentation never enter extension views, storage, exports or content-script messages." + }, + { + "id": "bexp-SETUP18-C06", + "scenario": "Cancellation or connection loss during shared setup parity and documentation preserves already verified effects and surfaces unconfirmed cleanup separately." + }, + { + "id": "bexp-SETUP18-C07", + "scenario": "An unavailable or incompatible local companion for shared setup parity and documentation offers the documented nonsecret planning/handoff path without claiming application." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/features/WORK.v1.json b/specs/browser-extension/features/WORK.v1.json new file mode 100644 index 000000000..c9fb15197 --- /dev/null +++ b/specs/browser-extension/features/WORK.v1.json @@ -0,0 +1,406 @@ +{ + "id": "WORK", + "title": "Personal workspaces and platform ergonomics", + "features": [ + { + "id": "BEX-WORK-01", + "family": "WORK", + "title": "My work overview", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Local control center", + "userOutcome": "Aggregate explicit selected assigned issues, authored PRs and review requests with per-source completeness.", + "boundaryAcceptance": "The default scope never expands to every private organization repository.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK01-C01", + "scenario": "Given the eligible local control center and verified input, choosing my work overview produces this observable result: Aggregate explicit selected assigned issues, authored PRs and review requests with per-source completeness." + }, + { + "id": "bexp-WORK01-C02", + "scenario": "For my work overview, exercise the concrete boundary: The default scope never expands to every private organization repository." + }, + { + "id": "bexp-WORK01-C03", + "scenario": "A denied, truncated or expired source for my work overview shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-WORK01-C04", + "scenario": "Changing the selected repository/account/revision while my work overview is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-02", + "family": "WORK", + "title": "Named repository workspaces", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Control center", + "userOutcome": "Create bounded personal workspace collections and switch context without changing repository policy.", + "boundaryAcceptance": "Private membership and metadata remain account-partitioned and excluded from ordinary exports.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK02-C01", + "scenario": "Given the eligible control center and verified input, choosing named repository workspaces produces this observable result: Create bounded personal workspace collections and switch context without changing repository policy." + }, + { + "id": "bexp-WORK02-C02", + "scenario": "For named repository workspaces, exercise the concrete boundary: Private membership and metadata remain account-partitioned and excluded from ordinary exports." + }, + { + "id": "bexp-WORK02-C03", + "scenario": "An invalid or future-schema change to named repository workspaces preserves the previous complete settings revision." + }, + { + "id": "bexp-WORK02-C04", + "scenario": "Named repository workspaces survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-03", + "family": "WORK", + "title": "Work queues and next actions", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Control center", + "userOutcome": "Arrange personal reading/review/maintenance queues with source-linked next actions.", + "boundaryAcceptance": "Personal order cannot masquerade as a shared repository priority or SLA.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK03-C01", + "scenario": "Given the eligible control center and verified input, choosing work queues and next actions produces this observable result: Arrange personal reading/review/maintenance queues with source-linked next actions." + }, + { + "id": "bexp-WORK03-C02", + "scenario": "For work queues and next actions, exercise the concrete boundary: Personal order cannot masquerade as a shared repository priority or SLA." + }, + { + "id": "bexp-WORK03-C03", + "scenario": "An invalid or future-schema change to work queues and next actions preserves the previous complete settings revision." + }, + { + "id": "bexp-WORK03-C04", + "scenario": "Work queues and next actions survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-04", + "family": "WORK", + "title": "Context-preserving split navigation", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "GitHub links and command palette", + "userOutcome": "Offer explicit open-in-current or new-tab actions while preserving native browser behavior.", + "boundaryAcceptance": "The extension never scans all open tabs or steals focus from another application.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK04-C01", + "scenario": "Given the eligible github links and command palette and verified input, choosing context-preserving split navigation produces this observable result: Offer explicit open-in-current or new-tab actions while preserving native browser behavior." + }, + { + "id": "bexp-WORK04-C02", + "scenario": "For context-preserving split navigation, exercise the concrete boundary: The extension never scans all open tabs or steals focus from another application." + }, + { + "id": "bexp-WORK04-C03", + "scenario": "After context-preserving split navigation mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-05", + "family": "WORK", + "title": "View and reading profiles", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "All supported GitHub pages", + "userOutcome": "Switch bounded named comfortable, compact and review profiles with a preview of changed features.", + "boundaryAcceptance": "Profiles cannot grant permissions or hide required native actions.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK05-C01", + "scenario": "Given the eligible all supported github pages and verified input, choosing view and reading profiles produces this observable result: Switch bounded named comfortable, compact and review profiles with a preview of changed features." + }, + { + "id": "bexp-WORK05-C02", + "scenario": "For view and reading profiles, exercise the concrete boundary: Profiles cannot grant permissions or hide required native actions." + }, + { + "id": "bexp-WORK05-C03", + "scenario": "An invalid or future-schema change to view and reading profiles preserves the previous complete settings revision." + }, + { + "id": "bexp-WORK05-C04", + "scenario": "View and reading profiles survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-06", + "family": "WORK", + "title": "Local draft and session workspace", + "delivery": "required-for-product-acceptance", + "mode": "settings", + "surface": "Control center", + "userOutcome": "Inspect explicitly saved session snippets, notes and pending drafts with deletion and export choices.", + "boundaryAcceptance": "Disconnect cannot publish a draft or silently delete an explicitly persisted authored note.", + "permissionProfile": "personal-settings", + "dataSource": "extension-owned personal state", + "freshnessRule": "committed settings revision", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK06-C01", + "scenario": "Given the eligible control center and verified input, choosing local draft and session workspace produces this observable result: Inspect explicitly saved session snippets, notes and pending drafts with deletion and export choices." + }, + { + "id": "bexp-WORK06-C02", + "scenario": "For local draft and session workspace, exercise the concrete boundary: Disconnect cannot publish a draft or silently delete an explicitly persisted authored note." + }, + { + "id": "bexp-WORK06-C03", + "scenario": "An invalid or future-schema change to local draft and session workspace preserves the previous complete settings revision." + }, + { + "id": "bexp-WORK06-C04", + "scenario": "Local draft and session workspace survives a supported settings migration and remains isolated from another account/repository." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-07", + "family": "WORK", + "title": "Unavailable capability explanations", + "delivery": "required-for-product-acceptance", + "mode": "local", + "surface": "Every feature entry point", + "userOutcome": "Explain missing permission, producer, source, browser API or page support with one useful recovery action.", + "boundaryAcceptance": "The UI never implies a feature is complete merely because a button rendered.", + "permissionProfile": "page-local", + "dataSource": "visible DOM/URL and nonsecret preferences", + "freshnessRule": "mounted page generation", + "default": "available-with-eligible-page", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK07-C01", + "scenario": "Given the eligible every feature entry point and verified input, choosing unavailable capability explanations produces this observable result: Explain missing permission, producer, source, browser API or page support with one useful recovery action." + }, + { + "id": "bexp-WORK07-C02", + "scenario": "For unavailable capability explanations, exercise the concrete boundary: The UI never implies a feature is complete merely because a button rendered." + }, + { + "id": "bexp-WORK07-C03", + "scenario": "After unavailable capability explanations mounts, a native refresh and then disable restore native focus/content with no duplicate control or leaked resource." + } + ], + "nativeTarget": "none" + }, + { + "id": "BEX-WORK-08", + "family": "WORK", + "title": "Upgrade and compatibility center", + "delivery": "required-for-product-acceptance", + "mode": "read", + "surface": "Control center", + "userOutcome": "Show extension, Action contract, setup companion and browser compatibility with exact sources.", + "boundaryAcceptance": "Unknown versions remain unknown and no release asset is executed automatically.", + "permissionProfile": "selected-repository-read", + "dataSource": "canonical allowlisted GitHub reads or verified Action publications", + "freshnessRule": "I1-I6 observation and identity fence", + "default": "explicit-opt-in", + "optionalBrowserPermissions": [], + "browsers": [ + "chrome", + "firefox", + "safari" + ], + "privacy": "session-first-private-data; no telemetry; redacted exports; explicit persistence only for authored personal state", + "activation": "eligibility before mount; user gesture for reads beyond the current page, drafts, writes and optional grants", + "coexistence": "omit equivalent native control; explain loaded scope; preserve native content, drafts, checks and recovery", + "accessibility": "keyboard/focus, screen reader, 200% zoom/320 CSS px, themes, reduced motion; complete en/es/fr/pt", + "requirements": [ + "CAT-WORK" + ], + "documentation": [ + "docs/browser-extension/features.mdx", + "docs/browser-extension/configuration.mdx", + "docs/browser-extension/troubleshooting.mdx" + ], + "tests": [ + { + "id": "bexp-WORK08-C01", + "scenario": "Given the eligible control center and verified input, choosing upgrade and compatibility center produces this observable result: Show extension, Action contract, setup companion and browser compatibility with exact sources." + }, + { + "id": "bexp-WORK08-C02", + "scenario": "For upgrade and compatibility center, exercise the concrete boundary: Unknown versions remain unknown and no release asset is executed automatically." + }, + { + "id": "bexp-WORK08-C03", + "scenario": "A denied, truncated or expired source for upgrade and compatibility center shows its exact unavailable/partial reason instead of a zero or success." + }, + { + "id": "bexp-WORK08-C04", + "scenario": "Changing the selected repository/account/revision while upgrade and compatibility center is loading prevents the late result from rendering." + } + ], + "nativeTarget": "none" + } + ] +} diff --git a/specs/browser-extension/manifest-v1.schema.json b/specs/browser-extension/manifest-v1.schema.json new file mode 100644 index 000000000..22cddb062 --- /dev/null +++ b/specs/browser-extension/manifest-v1.schema.json @@ -0,0 +1,65 @@ +{ + "type": "object", + "additionalProperties": false, + "required": [ + "schemaVersion", + "enabled", + "repositoryId", + "producerActorId", + "workflowPaths", + "capabilities", + "statusSchemaMajor", + "publication" + ], + "properties": { + "schemaVersion": { + "const": 1 + }, + "enabled": { + "type": "boolean" + }, + "repositoryId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "producerActorId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "workflowPaths": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^\\.github/workflows/[A-Za-z0-9_.-]+\\.ya?ml$" + }, + "maxItems": 8, + "minItems": 1, + "uniqueItems": true + }, + "capabilities": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 48, + "pattern": "^[a-z][a-z0-9-]{0,39}\\.v[1-9][0-9]{0,2}$" + }, + "maxItems": 16, + "minItems": 0, + "uniqueItems": true + }, + "statusSchemaMajor": { + "const": 1 + }, + "publication": { + "const": "current-status-comment" + } + }, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "urn:vypdev:copilot:browser-extension:manifest:1", + "title": "Proposed browser connection manifest v1" +} diff --git a/specs/browser-extension/requests-v2.schema.json b/specs/browser-extension/requests-v2.schema.json new file mode 100644 index 000000000..8f79b47d9 --- /dev/null +++ b/specs/browser-extension/requests-v2.schema.json @@ -0,0 +1,104 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://vypdev.github.io/copilot/specs/browser-extension/requests-v2.schema.json", + "type": "object", + "additionalProperties": false, + "required": [ + "schemaVersion", + "repositoryId", + "producerActorId", + "commands" + ], + "properties": { + "schemaVersion": { + "const": 2 + }, + "repositoryId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "producerActorId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "commands": { + "type": "array", + "minItems": 1, + "maxItems": 32, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "contexts", + "requiresWriteActor", + "requiresVerifiedBranch", + "effect", + "agent" + ], + "properties": { + "name": { + "enum": [ + "help", + "plan", + "clarify", + "estimate", + "test-plan", + "explain", + "diagnose", + "analyze", + "review", + "findings", + "recheck", + "sdd-diff", + "status", + "doctor", + "history", + "description", + "fix", + "dismiss", + "implement", + "remember", + "sync-branch" + ] + }, + "contexts": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "uniqueItems": true, + "items": { + "enum": [ + "conversation", + "review-thread" + ] + } + }, + "requiresWriteActor": { + "type": "boolean" + }, + "requiresVerifiedBranch": { + "type": "boolean" + }, + "effect": { + "enum": [ + "files", + "finding-state", + "pr-description", + "publication" + ] + }, + "agent": { + "enum": [ + "never", + "conditional", + "may-run" + ] + } + } + } + } + } +} diff --git a/specs/browser-extension/status-v1.schema.json b/specs/browser-extension/status-v1.schema.json new file mode 100644 index 000000000..d6b8e41f7 --- /dev/null +++ b/specs/browser-extension/status-v1.schema.json @@ -0,0 +1,929 @@ +{ + "type": "object", + "additionalProperties": false, + "required": [ + "schemaVersion", + "capabilities", + "identity", + "producer", + "publication", + "native", + "lifecycle", + "assessment", + "links", + "sdd", + "findings", + "commands", + "branch" + ], + "properties": { + "schemaVersion": { + "const": 1 + }, + "capabilities": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 48, + "pattern": "^[a-z][a-z0-9-]{0,39}\\.v[1-9][0-9]{0,2}$" + }, + "maxItems": 16, + "minItems": 0, + "uniqueItems": true + }, + "identity": { + "type": "object", + "additionalProperties": false, + "required": [ + "repositoryId", + "kind", + "number" + ], + "properties": { + "repositoryId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "kind": { + "enum": [ + "issue", + "pull-request" + ] + }, + "number": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "headSha": { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[a-f0-9]{40}$" + }, + "baseSha": { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[a-f0-9]{40}$" + } + }, + "allOf": [ + { + "if": { + "properties": { + "kind": { + "const": "pull-request" + } + } + }, + "then": { + "required": [ + "headSha", + "baseSha" + ] + }, + "else": { + "not": { + "anyOf": [ + { + "required": [ + "headSha" + ] + }, + { + "required": [ + "baseSha" + ] + } + ] + } + } + } + ] + }, + "producer": { + "type": "object", + "additionalProperties": false, + "required": [ + "actorId", + "runId", + "attempt", + "workflowPath", + "sourceCommit", + "actionVersion", + "configurationDigest" + ], + "properties": { + "actorId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "runId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "attempt": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "workflowPath": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^\\.github/workflows/[A-Za-z0-9_.-]+\\.ya?ml$" + }, + "sourceCommit": { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[a-f0-9]{40}$" + }, + "actionVersion": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$" + }, + "configurationDigest": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^[a-f0-9]{64}$" + } + } + }, + "publication": { + "type": "object", + "additionalProperties": false, + "required": [ + "commentId", + "generation", + "observedAt", + "outcome" + ], + "properties": { + "commentId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "generation": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "observedAt": { + "type": "string", + "format": "date-time", + "maxLength": 30, + "pattern": "Z$" + }, + "outcome": { + "enum": [ + "complete", + "partial", + "failed", + "pending", + "canceled" + ] + } + } + }, + "native": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "reason" + ], + "properties": { + "state": { + "enum": [ + "open", + "closed" + ] + }, + "reason": { + "enum": [ + "completed", + "not-planned", + "reopened", + "duplicate", + "unknown", + null + ] + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "merged" + ], + "properties": { + "state": { + "enum": [ + "open", + "closed" + ] + }, + "merged": { + "type": "boolean" + } + }, + "allOf": [ + { + "if": { + "properties": { + "merged": { + "const": true + } + } + }, + "then": { + "properties": { + "state": { + "const": "closed" + } + } + } + } + ] + } + ] + }, + "lifecycle": { + "type": "object", + "additionalProperties": false, + "required": [ + "phase", + "activity", + "waitingFor" + ], + "properties": { + "phase": { + "enum": [ + "planned", + "specifying", + "working", + "reviewing", + "changes-requested", + "ready", + "verified", + "blocked", + "unknown" + ] + }, + "activity": { + "enum": [ + "idle", + "processing", + "unknown" + ] + }, + "waitingFor": { + "enum": [ + "none", + "maintainer", + "issue-author", + "pr-author", + "unknown" + ] + } + } + }, + "assessment": { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "policyDigest", + "coverage", + "currentFindingCount", + "nextAction" + ], + "properties": { + "state": { + "enum": [ + "not-applicable", + "unavailable", + "pending", + "blocked", + "satisfied" + ] + }, + "policyDigest": { + "anyOf": [ + { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^[a-f0-9]{64}$" + }, + { + "type": "null" + } + ] + }, + "coverage": { + "enum": [ + "complete", + "partial", + "unknown" + ] + }, + "currentFindingCount": { + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 10000 + }, + { + "type": "null" + } + ] + }, + "nextAction": { + "enum": [ + "none", + "inspect-findings", + "open-question", + "inspect-run", + "inspect-blocker", + "wait", + "select-pr", + "open-native", + "review-result", + "refresh" + ] + } + } + }, + "links": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "number" + ], + "properties": { + "kind": { + "enum": [ + "issue", + "pull-request" + ] + }, + "number": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "id" + ], + "properties": { + "kind": { + "const": "run" + }, + "id": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + } + } + } + ] + }, + "maxItems": 12, + "minItems": 0 + }, + "sdd": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "path", + "commitSha", + "pendingQuestionIds" + ], + "properties": { + "state": { + "enum": [ + "not-required", + "awaiting-answers", + "revision-pending", + "ready", + "invalid", + "unavailable" + ] + }, + "path": { + "anyOf": [ + { + "type": "string", + "minLength": 1, + "maxLength": 300, + "pattern": "^specs/(?!.*(?:^|/)\\.\\.(?:/|$))[^\\x00-\\x1f\\\\]+\\.md$" + }, + { + "type": "null" + } + ] + }, + "commitSha": { + "anyOf": [ + { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[a-f0-9]{40}$" + }, + { + "type": "null" + } + ] + }, + "pendingQuestionIds": { + "type": "array", + "items": { + "enum": [ + "Q1", + "Q2", + "Q3", + "Q4", + "Q5", + "Q6", + "Q7", + "Q8" + ] + }, + "maxItems": 8, + "minItems": 0, + "uniqueItems": true + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "ready" + } + } + }, + "then": { + "properties": { + "path": { + "type": "string" + }, + "commitSha": { + "type": "string" + }, + "pendingQuestionIds": { + "maxItems": 0 + } + } + } + } + ] + }, + { + "type": "null" + } + ] + }, + "findings": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "complete", + "total", + "items" + ], + "properties": { + "complete": { + "type": "boolean" + }, + "total": { + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 10000 + }, + { + "type": "null" + } + ] + }, + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "reviewCommentId", + "reviewId", + "path", + "line", + "severity", + "state", + "headSha", + "summary" + ], + "properties": { + "id": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$" + }, + "reviewCommentId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "reviewId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "path": { + "type": "string", + "minLength": 1, + "maxLength": 300, + "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))[^\\x00-\\x1f\\\\]+$" + }, + "line": { + "anyOf": [ + { + "type": "integer", + "minimum": 1, + "maximum": 10000000 + }, + { + "type": "null" + } + ] + }, + "severity": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info", + "unknown" + ] + }, + "state": { + "enum": [ + "open", + "reopened", + "verification-required", + "fixed", + "dismissed", + "obsolete", + "unknown" + ] + }, + "headSha": { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[a-f0-9]{40}$" + }, + "summary": { + "type": "string", + "minLength": 1, + "maxLength": 300 + } + } + }, + "maxItems": 100, + "minItems": 0 + } + } + }, + { + "type": "null" + } + ] + }, + "commands": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "context" + ], + "properties": { + "name": { + "enum": [ + "status", + "analyze", + "fix", + "dismiss" + ] + }, + "context": { + "enum": [ + "conversation", + "review-thread" + ] + }, + "findingId": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$" + }, + "reviewCommentId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + } + }, + "allOf": [ + { + "if": { + "properties": { + "name": { + "enum": [ + "fix", + "dismiss" + ] + } + } + }, + "then": { + "required": [ + "findingId", + "reviewCommentId" + ], + "properties": { + "context": { + "const": "review-thread" + } + } + }, + "else": { + "properties": { + "context": { + "const": "conversation" + } + }, + "not": { + "anyOf": [ + { + "required": [ + "findingId" + ] + }, + { + "required": [ + "reviewCommentId" + ] + } + ] + } + } + } + ] + }, + "maxItems": 16, + "minItems": 0 + }, + "branch": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "repositoryId", + "ref", + "commitSha" + ], + "properties": { + "state": { + "enum": [ + "verified", + "pending", + "unavailable", + "not-applicable" + ] + }, + "repositoryId": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "ref": { + "anyOf": [ + { + "type": "string", + "minLength": 1, + "maxLength": 256, + "pattern": "^(?!/)(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\[\\\\\\x00-\\x20])[A-Za-z0-9][^/]*(?:/[^/]+)*$" + }, + { + "type": "null" + } + ] + }, + "commitSha": { + "anyOf": [ + { + "type": "string", + "pattern": "^[a-f0-9]{40}$", + "minLength": 40, + "maxLength": 40 + }, + { + "type": "null" + } + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "verified" + } + } + }, + "then": { + "properties": { + "ref": { + "type": "string" + }, + "commitSha": { + "type": "string" + } + } + } + } + ] + }, + { + "type": "null" + } + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "identity": { + "properties": { + "kind": { + "const": "issue" + } + } + } + } + }, + "then": { + "properties": { + "native": { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "reason" + ], + "properties": { + "state": { + "enum": [ + "open", + "closed" + ] + }, + "reason": { + "enum": [ + "completed", + "not-planned", + "reopened", + "duplicate", + "unknown", + null + ] + } + } + } + } + }, + "else": { + "properties": { + "native": { + "type": "object", + "additionalProperties": false, + "required": [ + "state", + "merged" + ], + "properties": { + "state": { + "enum": [ + "open", + "closed" + ] + }, + "merged": { + "type": "boolean" + } + }, + "allOf": [ + { + "if": { + "properties": { + "merged": { + "const": true + } + } + }, + "then": { + "properties": { + "state": { + "const": "closed" + } + } + } + } + ] + } + } + } + }, + { + "if": { + "properties": { + "identity": { + "properties": { + "kind": { + "const": "pull-request" + } + } + }, + "assessment": { + "properties": { + "state": { + "const": "satisfied" + } + } + } + } + }, + "then": { + "properties": { + "assessment": { + "properties": { + "policyDigest": { + "type": "string" + }, + "coverage": { + "const": "complete" + } + } + } + } + } + } + ], + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "urn:vypdev:copilot:browser-extension:status:1", + "title": "Proposed browser status snapshot v1", + "$comment": "Specification artifact only. Byte/UTF-8/duplicate-key/provenance/freshness/semantic checks are additionally required by the integration SDD." +} diff --git a/specs/catalog.json b/specs/catalog.json index fd56ff5d0..deb93da9a 100644 --- a/specs/catalog.json +++ b/specs/catalog.json @@ -1392,7 +1392,8 @@ "docs/guides/work-with-the-bot.mdx", "docs/guides/releases-and-hotfixes.mdx", "docs/security-operations/operations/verification.mdx", - "docs/security-operations/operations/upgrade-rollback.mdx" + "docs/security-operations/operations/upgrade-rollback.mdx", + "specs/github-browser-extension-control-center-and-setup.md" ] }, { @@ -2710,6 +2711,59 @@ "docs/bugbot/configuration.mdx", "docs/development/architecture.mdx" ] + }, + { + "id": "github-browser-extension", + "title": "Complete GitHub productivity extension and integrated Copilot setup", + "status": "proposed", + "scope": "Complete proposed desktop product: 150 required functions, packaged local center, full compatible Action integration, shared setup and 803 distinct future acceptance cases; runtime remains unimplemented", + "owner": "Copilot maintainers", + "lastVerified": "2026-10-25", + "specs": [ + "specs/github-browser-extension.md", + "specs/github-browser-extension-action-integration.md", + "specs/github-browser-extension-platforms-and-delivery.md", + "specs/github-browser-extension-functional-catalog.md", + "specs/github-browser-extension-control-center-and-setup.md" + ], + "workflows": [], + "entrypoints": [ + "src/actions/github_action.ts" + ], + "code": [ + "src/application/usecases/read_copilot_status_workflow.ts", + "src/application/ports/pull_request_status_read_ports.ts" + ], + "tests": [ + "src/application/usecases/__tests__/read_copilot_status_workflow.test.ts" + ], + "documentation": [ + "docs/development/specifications.mdx", + "docs/issues/comment-commands.mdx", + "specs/browser-extension/manifest-v1.schema.json", + "specs/browser-extension/status-v1.schema.json", + "specs/browser-extension/examples/manifest-v1.json", + "specs/browser-extension/examples/status-pr-v1.json", + "specs/browser-extension/examples/status-issue-v1.json", + "specs/browser-extension/examples/status-invalid-head-v1.json", + "specs/browser-extension/feature-catalog.v1.json", + "specs/browser-extension/feature-catalog.schema.json", + "specs/browser-extension/requests-v2.schema.json", + "specs/browser-extension/examples/requests-v2.json", + "specs/browser-extension/feature-catalog-index.schema.json", + "specs/browser-extension/features/NAV.v1.json", + "specs/browser-extension/features/CODE.v1.json", + "specs/browser-extension/features/REVIEW.v1.json", + "specs/browser-extension/features/ISSUE.v1.json", + "specs/browser-extension/features/SEARCH.v1.json", + "specs/browser-extension/features/NOTIFY.v1.json", + "specs/browser-extension/features/CI.v1.json", + "specs/browser-extension/features/RELEASE.v1.json", + "specs/browser-extension/features/WORK.v1.json", + "specs/browser-extension/features/COPILOT.v1.json", + "specs/browser-extension/features/CENTER.v1.json", + "specs/browser-extension/features/SETUP.v1.json" + ] } ] } diff --git a/specs/github-browser-extension-action-integration.md b/specs/github-browser-extension-action-integration.md new file mode 100644 index 000000000..49ce536f8 --- /dev/null +++ b/specs/github-browser-extension-action-integration.md @@ -0,0 +1,727 @@ +# GitHub Browser Extension — Action Integration Contract + +- Status: Ready for review — proposed producer and client contract, not implemented +- Date: 2026-10-25 +- Catalog capability ID: `github-browser-extension` +- Last verified: 2026-10-25, source/contract review only +- Owners: Copilot maintainers; Action producer and extension reader have separate release responsibility +- Scope: Discover and read trustworthy current Action snapshots and prepare supported native GitHub drafts. +- Related issues/PRs: [#694](https://github.com/vypdev/copilot/issues/694) +- Required review gates: product UX, architecture, testing, documentation, security/operations +- Open decisions blocking design readiness: None. Producer implementation and compatible release are prerequisites for connected mode. + +## 1. Executive summary + +The Action will publish a small versioned projection in its existing current +status publication. A reviewed configuration file on the repository's default +branch identifies the producer and capabilities. The extension reads these +through GitHub's API; it never turns a browser visit into a status comment or an +Action run. Standalone features work before producer support ships. + +```text +Repository opt-in → trusted-default configuration → bounded source lookup + → validate producer/target/run/schema → reread native identity + → render timestamped assessment → optionally prepare native draft +``` + +The assessment is information at an observed revision, not a merge authorization +or an independent replacement for native branch protection. [Product](github-browser-extension.md) +owns its presentation and [platforms](github-browser-extension-platforms-and-delivery.md) +owns credentials, browser isolation and packaging. + +## 2. Problem, current behavior, and evidence + +Existing status, SDD and Bugbot publications contain useful facts, but internal +markers are not a declared external API. Recreating their meaning with DOM +selectors or check-name matching would lose provenance, completeness and +revision fencing. Current read status also publishes a reply when invoked as a +comment command; the extension needs passive reads instead. + +Observed implementation boundaries: +- `src/application/usecases/read_copilot_status_workflow.ts`: combines native + completion, SDD and PR readiness through read ports. +- `src/application/ports/pull_request_status_read_ports.ts`: read policy, + revision and evidence, without approval submission. +- `src/application/policies/status_command_policy.ts` and + `sdd_status_policy.ts`: public presentation projections, not transport schemas. +- `src/application/policies/bugbot_review_ownership_policy.ts`: existing trusted + author filtering; a browser reader additionally checks numeric identity. +- [Exact-revision readiness](guarded-pull-request-approval-status.md), + [SDD readiness](pre-branch-sdd-status-readiness.md), + [finding reconciliation](bugbot-review-state-reconciliation.md), + [comment authorization](comment-automation-and-authorization.md), + [publication](semantic-github-publication-and-notification.md). + +Prospective classification: not applicable to as-built reconstruction. The new +manifest/envelope and source pointer below are proposed additions. No current +Action version is claimed to implement them. + +## 3. Actors, surfaces, and terminology + +| Actor | Owns | Surface | +|---|---|---| +| Maintainer | Reviewed producer configuration and repository connection eligibility | Default-branch configuration and PR review | +| Action | Authoritative projections, monotonic publication and authorization | Existing status card, checks, run/summary | +| Extension | Validation, freshness, cache and personal presentation | Context/findings panel and options | +| User | Optional read credential and native submission | Extension connection page and GitHub composer | +| GitHub | Repository/PR/run identities and access policy | REST/native UI | + +`source` is an API-verified publication; `locator` is only an untrusted hint to +find it. `generation` orders producer snapshots; `pageGeneration` orders local +navigation. `assessment` is a timestamped Action report; `native` facts are fresh +GitHub reads. `unavailable` differs from `pending` and `not-applicable`. + +## 4. Goals, non-goals, and fixed invariants + +- **I1 — Discovery:** read an explicit default-branch manifest; absence or denied + access disables connected capabilities without disabling standalone ones. +- **I2 — Schema:** accept only bounded versioned contracts with compatible + capabilities; malformed/future-major data cannot become success. +- **I3 — Provenance:** verify author ID, repository, conversation, run/attempt, + workflow source and source-comment identity before projecting connected facts. +- **I4 — Ownership:** preserve native state, lifecycle/activity/waiting dimensions, + SDD/finding semantics, completeness and historical distinction. +- **I5 — Freshness:** fence head/base/public configuration/native state and discard superseded + generations, stale/foreign results and out-of-order responses. +- **I6 — Bounded reads:** centralized request/caching/rate-limit policy creates no + repository mutation, command comment or agent invocation. +- **I7 — Authentication:** optional user-owned read connection with exact origin, + selected repository bounds and session-only credential handling under D4. +- **I8 — Drafts:** known commands and authoritative target contexts only; user + submission and all Action execution checks remain separate. +- **I9 — Untrusted input:** validate/sanitize URLs, strings, counts, messages and + locators; never execute remote content or accept arbitrary HTTP commands. +- **I10 — Producer compatibility:** additive publication with explicit version + rollout, idempotency, partial-publication recovery and existing noise budgets. + +Normative tables refine I1–I10. The complete product additionally includes the closed operation and full-command contracts in §11.3 and I8 below. Non-goals: arbitrary API writes, new merge policy, +token provisioning service, realtime push server, browser-side AI, or reusing bot +credentials. A trusted snapshot cannot grant user permissions or bypass checks. + +## 5. Current versus proposed journey + +| Stage | Current | Proposed | +|---|---|---| +| Discover | Infer presence from visible comments/labels | I1 reviewed manifest and explicit user opt-in | +| Read | Human compares multiple sources | I3/I5 validated projection plus source links | +| Missing evidence | Easy to confuse with zero/ready | Independent unavailable/partial fields | +| Request | Remember command vocabulary and event restrictions | I8 exact-context draft preview | +| Execute | Existing parser/auth/verification/publication | Same Action contract after native submission | + +```mermaid +sequenceDiagram + participant U as User + participant E as Extension background reader + participant G as GitHub API + participant A as Action publication + U->>E: Connect selected repository + E->>G: Repository/default-ref/manifest reads + E->>G: Source comment and run metadata + E->>G: Current issue or PR/head/base + E-->>U: Verified snapshot or explicit unavailable state + U->>E: Prepare supported request + E-->>U: Native composer preview, no submission + U->>G: Submit native comment + G->>A: Existing workflow admission and execution + A->>G: Update current status publication +``` + +Text equivalent: user opts in, reader validates default configuration/source and +native identity, renders a snapshot, user prepares then submits a request, and +the existing Action workflow publishes its result. + +## 6. Functional behavior and state model + +### 6.1 Manifest and passive transport + +Proposed path: `.copilot/browser-extension.json` on the canonical default branch. +The reader resolves repository numeric identity/default branch, pins its commit, +then reads the file at that commit. Candidate/PR branch files cannot configure +trust. A default-ref/policy change invalidates cache and is fenced again before +showing complete evidence. A denied read is unavailable, not proof of absence. + +```json +{ + "schemaVersion": 1, + "enabled": true, + "repositoryId": 1, + "producerActorId": 2, + "workflowPaths": [".github/workflows/copilot_issue.yml", ".github/workflows/copilot_pull_request.yml", ".github/workflows/copilot_issue_comment.yml"], + "capabilities": ["context.v1", "findings.v1", "command-drafts.v1"], + "statusSchemaMajor": 1, + "publication": "current-status-comment" +} +``` + +IDs 1/2 are illustrative, not this repository's real IDs. The manifest is at most +8 KiB, has no unknown v1 keys, ≤8 exact workflow paths and ≤16 well-formed capability +tokens (unsupported tokens are ignored, never executed). IDs are positive safe integers. Paths are reviewed repository-relative +workflow paths, with no traversal/wildcards/URLs; no credential can be included. +The example workflow list is illustrative: a real manifest must name every +reviewed installed route that publishes the shared status, including push or +review-thread routes when enabled. A missing route is never trusted by name +similarity. Producer rollout validates its actual workflow inventory against the +reviewed manifest; optional routes are added only when installed and enabled. +Missing capability hides just its feature. `enabled:false` stops connected reads +after configuration validation; no remote toggle may override a personal pause. + +The Action adds a closed machine envelope to the *existing* current status card, +not a new comment per refresh. Proposed hidden format: + +```text + +``` + +The marker is framing, never evidence by itself. Decode ≤24 KiB, reject duplicate +markers/JSON keys, invalid UTF-8 or excessive nesting (maximum 8). Total comment +publication is bounded to 60 KiB UTF-8 including its human content. Escaping and +base64url framing prevent comment/HTML terminators in untrusted text. A SHA-256 +digest is for consistency/idempotency, not a signature or trust substitute. + +For efficient location, a new optional `browserStatus` source pointer in the +existing Action-owned conversation configuration may carry `{schemaVersion:1, +commentId:123}`. The pointer is **untrusted**: resolve it through the canonical +conversation comment API, then verify I3–I5. If absent, consider API-validated +comment IDs already visible on the page, then a bounded scan of at most three +100-comment pages (first and latest pages, following actual pagination links). +If the search cannot prove completeness, label discovery partial and never claim +no producer or latest aggregate state from an arbitrary subset. Offer Open +native status; do not scan the whole repository on a page load. Inconsistent +multiple canonical cards are unavailable until producer reconciliation, not a +"pick newest prose" heuristic. The pointer does not itself certify latest state. + +### 6.2 Snapshot contract + +Representative **structural** example; timestamps, IDs, digests and revisions are +illustrative and become stale outside a matching test clock/fixture. + +```json +{ + "schemaVersion": 1, + "capabilities": ["context.v1", "findings.v1", "command-drafts.v1"], + "identity": {"repositoryId": 1, "kind": "pull-request", "number": 158, "headSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "baseSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}, + "producer": {"actorId": 2, "runId": 300, "attempt": 1, "workflowPath": ".github/workflows/copilot_pull_request.yml", "sourceCommit": "cccccccccccccccccccccccccccccccccccccccc", "actionVersion": "3.0.0", "configurationDigest": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"}, + "publication": {"commentId": 123, "generation": 7, "observedAt": "2026-10-25T10:42:00Z", "outcome": "complete"}, + "native": {"state": "open", "merged": false}, + "lifecycle": {"phase": "changes-requested", "activity": "idle", "waitingFor": "pr-author"}, + "assessment": {"state": "blocked", "policyDigest": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "coverage": "complete", "currentFindingCount": 1, "nextAction": "inspect-findings"}, + "links": [{"kind": "issue", "number": 142}, {"kind": "run", "id": 300}], + "branch": {"state": "verified", "repositoryId": 1, "ref": "feature/142-example", "commitSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, + "sdd": {"state": "ready", "path": "specs/example.md", "commitSha": "ffffffffffffffffffffffffffffffffffffffff", "pendingQuestionIds": []}, + "findings": {"complete": true, "total": 1, "items": [{"id": "F-1", "reviewCommentId": 456, "reviewId": 789, "path": "src/example.ts", "line": 12, "severity": "high", "state": "open", "headSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "summary": "Validate the input before processing it."}]}, + "commands": [{"name": "status", "context": "conversation"}, {"name": "analyze", "context": "conversation"}, {"name": "fix", "context": "review-thread", "findingId": "F-1", "reviewCommentId": 456}] +} +``` + +Every SHA field in v1 uses the repository's supported full SHA-1 representation, +40 lowercase hexadecimal characters. Unsupported repository hash algorithms +produce incompatible, not truncation. A policy/configuration digest is exactly +64 lowercase hex. Invalid SHA variants belong in negative fixtures, not in a +successful projection. + +Contract field rules: + +| Field | Closed contract / bound / ownership | +|---|---| +| identity | Exact repo ID, issue/PR kind and positive number; PR requires head/base, issue forbids invented PR identity | +| producer | Expected actor ID, positive run ID/attempt, allowed workflow path, full source commit and bounded semver (≤64 chars); config digest binds reviewed manifest bytes | +| publication | API comment ID, positive generation ≤2^53−1, RFC3339 UTC time; outcome complete/partial/failed/pending/canceled | +| native | Native issue open/closed + reason, or PR open/closed + merged boolean; reread from GitHub, never trusted solely from payload | +| lifecycle | Phase: planned/specifying/working/reviewing/changes-requested/ready/verified/blocked/unknown; activity idle/processing/unknown; waitingFor none/maintainer/issue-author/pr-author/unknown | +| assessment | State not-applicable/unavailable/pending/blocked/satisfied; coverage complete/partial/unknown; finding count null or integer 0…10,000; policy digest required for satisfied PR assessment | +| links | ≤12 typed issue/PR numbers or run IDs; render URL from canonical GitHub identity, not arbitrary supplied HTML/URLs | +| branch | Null or verified/pending/unavailable/not-applicable, exact repository ID, safe ref ≤256 chars and full commit when verified; an issue never invents a ref from its title | +| sdd | not-required/awaiting-answers/revision-pending/ready/invalid/unavailable; safe specs path ≤300 chars, proven commit where ready; ≤8 question IDs Q1–Q8 | +| findings | ≤100 items within byte cap; total null or 0…10,000; complete false when truncated; stable ID ≤128 chars, path ≤300, summary ≤300; state open/reopened/verification-required/fixed/dismissed/obsolete/unknown | +| commands | ≤16 known name/context tuples; context conversation/review-thread only; exact finding/comment IDs required for mutations; does not assert current actor authorization | + +The normative structural schemas are [manifest v1](browser-extension/manifest-v1.schema.json) +and [status v1](browser-extension/status-v1.schema.json). Structural illustrations: +[manifest](browser-extension/examples/manifest-v1.json), +[PR](browser-extension/examples/status-pr-v1.json), +[issue](browser-extension/examples/status-issue-v1.json) and +[invalid head — expected rejection](browser-extension/examples/status-invalid-head-v1.json). +Positive and negative examples are validated as specification artifacts, not +running producer proof. +The schemas fix required/optional/null fields; this document adds semantic and +trust checks that JSON Schema alone cannot express. + +All v1 objects reject unknown keys; future additions require a schema/capability +revision and mixed-version fixtures. Unknown enum values make that projection +unavailable; never map them to success. Optional nullable fields are explicit in +the normative JSON Schema. ID uniqueness, counts versus items, UTF-8 byte cap, +relation consistency and enum invariants need semantic checks beyond JSON Schema. +In particular: `complete:true` implies `total === items.length`; a satisfied +assessment requires complete current evidence and matching policy/revision. + +### 6.3 Provenance and native identity + +I3 pipeline, in order: +1. Canonical repo read and explicit numeric repository opt-in; pin default ref and + validate manifest at that immutable commit. +2. Fetch source via GitHub API; ensure comment belongs to exact conversation and + repo, has manifest producer numeric user ID, and exactly one valid envelope. +3. Match envelope repo/kind/number/comment ID and configuration digest. Read the + run/attempt: repo, configured workflow path, source commit, native event and expected publication boundary + must match. PR run associations, where present, must include the exact PR. + Issue-event run metadata does not expose an authoritative issue number: bind + that target through the API-verified source comment/conversation and trusted + producer, and do not pretend the run title proves issue association. A user comment with + copied marker or login is insufficient. Do not infer authority from check name. +4. Running run can prove pending only. Completion requires successful completed + producer run/attempt; a payload cannot self-certify successful publication. +5. Re-read native conversation and, for PR, head/base; verify same-repo associations + and current public source configuration. Preserve the exact assessed policy + identity; if its current live identity cannot be read, show policy verification + as unknown rather than independently certifying it. Read failure is unavailable. +6. Commit the view only if pageGeneration, credential/account epoch, settings + version, source generation and final identities still match. + +For issue linkage: the Action producer uses its existing authoritative native +association query and publishes the complete result. The browser verifies the +reported objects through canonical GET reads and identifies the relationship as +an Action observation, not a fresh independent closure/linkage certificate. It +does not guess closing associations from REST timeline text, titles or numbers. Zero linked PRs is +not applicable. Multiple links show a chooser/links and require a PR-specific +view. Neither same number nor branch naming creates a link. Fork PRs may display +base-repository facts and verified review links, but the product does not prepare write +commands against a foreign head repository. Unresolved permissions stay unknown. + +### 6.4 State ownership, completeness and freshness + +Native close/merge wins over historical phase/progress. Durable phase, +temporary processing and human waiting are independent. SDD ready requires the +existing immutable publication proof; a branch name or published phase alone +does not prove readiness. Finding thread resolution alone does not mean fixed; +preserve the Action's fixed/dismissed/obsolete/verification-required semantics. + +Freshness defaults are fixed safety bounds: collected API facts ≤60 seconds old; +source observation age ≤120 seconds for a current running assessment. Future +timestamps >30 seconds beyond collection clock are invalid; a large clock skew +produces unavailable with clock guidance. Older completed assessments are shown +as historical until a normal Action update; **Refresh only rereads**, never +triggers work to manufacture fresh evidence. Completion is always phrased as +`Latest known Action assessment for this revision, observed at T`; it does not +promise that reviews/checks cannot change later at the same SHA. + +The browser does not request repository administration or Variables access to +recompute live approval policy. A policy digest in the source describes the +**assessed** policy. When current hidden policy inputs cannot be verified, render +`Action assessment completed at T; current policy verification unavailable`, not +`current policy satisfied` or `ready to merge`. Independently current native facts +and matching-revision findings may remain visible. Branch protection and the +existing trusted Action observer remain authoritative. A public policy/config +identity change that is observed always invalidates the assessment. This is a +fixed trust limitation, not permission to assume missing policy is unchanged. + +An observed PR head/base or manifest/policy change immediately clears the +current aggregate; changed revision also clears current finding counts. Late responses, generation regression and canceled collection +cannot restore it. Per-field provenance is retained in technical detail; +partial success preserves independently validated native/SDD facts while clearing +the aggregate assessment. States prioritize unresolved identity/unavailable, +then proven blocker, pending, then satisfied snapshot. A terminal native state +has its own explicit historical presentation. + +## 7. User-facing configuration + +The manifest values in §6.1 are repository-reviewed public configuration; personal +connection and preferences are separate. `enabled` defaults false if the manifest +is absent. Exactly one producer actor and the listed workflow paths are trusted +in v1. An unsupported manifest version requires operator upgrade/disable, never +a user override that accepts unverified evidence. Repository configuration +cannot request credentials, arbitrary URLs or automatically enable a browser. + +Recommended: public tokenless native browsing, then explicit connected opt-in +with session-only selected-repository read access if needed. Alternative: +remain standalone when organizational access is unavailable. Polling, byte caps, +URL allowlists, trust/freshness and no-submission limits are fixed, not sliders. + +## 8. Clean Architecture design + +| Boundary | Responsibility | Forbidden dependency/capability | +|---|---|---| +| Existing Action domain/application | Existing policy/evidence decisions; closed transport projection | Browser DOM/API types | +| Proposed Action publisher adapter | Encode/upsert envelope with existing status result | New policy/approval decisions or extra runs | +| Shared contract module | Types, schema, parser, pure validation | Node/GitHub SDK, DOM, credentials, side effects | +| Extension use cases | Discover/read/fence/cache and DraftRequest | Direct provider URLs or mutation SDK | +| Extension adapters | GitHub read endpoints, native composer, session storage | Arbitrary command/fetch gateway | +| Presentation | Immutable view model, text and links | Token, raw provider DTOs, authorization mutation | + +```mermaid +flowchart LR + AP[Existing Action projections] --> CP[Closed publication adapter] + CP --> GH[GitHub status comment and native facts] + BG[Extension read use case] --> CT[Pure contract validation] + BG --> RP[Semantic read ports] + GA[GitHub GET adapter] --> RP + GA --> GH + BG --> VM[Immutable context view] + VM --> UI[Page renderer] + UI --> DR[Prepare draft use case] +``` + +Text equivalent: existing Action decisions feed a publisher; a semantic GitHub +reader validates them through pure contracts and builds a view; drafting is a +separate use case with no submission capability. + +Proposed physical placement is in the platform companion. Future executable +checks parse imports/bundles, forbid Node/runtime imports in the shared/browser +modules, validate manifest/schema/golden fixtures and reject mutating HTTP +methods in the extension GitHub adapter. Opaque IDs and immutable inputs cross +ports; raw tokens/provider clients cannot cross into view models or DOM. + +## 9. UI/UX and content contract + +Use product §9 variants and source/time semantics. Additional connection copy: + +```text +Connect repository +Read context for this selected repository during this browser session. +No write permission is required. Requests are submitted separately in GitHub. +[Continue to connection settings] [Keep standalone features] + +Access unavailable +The selected credential cannot read the current status source. +Current readiness is unknown; your view preferences still work. +[Check selected repository access] [Open native GitHub] + +Publication incomplete +The branch was verified. The latest status publication could not finish. +No complete assessment is shown. [Inspect producer run] +``` + +Run IDs/head digests appear only in details. Safe typed links derive host/repo +from canonical identity; absent/malformed target produces plain unavailable text. +No diagram, color, hidden marker or badge alone communicates success. + +## 10. Failure, recovery, and cleanup + +### 10.1 Request budget and caching (I6) + +The evidence-reader background adapter is GET-only; optional writes use a different closed port under §11.3, never this read adapter or a model endpoint. Maximum two +requests in flight across the extension, one coalesced refresh per target. One +refresh is ≤12 GETs and ≤1 MiB decoded response data, with at most three comment +pages; limit overrun yields partial. Deduplicate tabs by account/repo/target and +manifest/source generation. Cache responses/ETags in protected session state; +no private evidence on disk or sync. Canonical identity read TTL is 60 seconds, +manifest revalidation 5 minutes unless an observed source/ref change invalidates it. + +Automatic refreshing is off in tokenless mode; at most 30 GETs/hour across all +anonymous targets, leaving margin within GitHub's published unauthenticated +limit. Connected authenticated mode: at most one refresh/60 seconds for the +foreground pending target, 120 GETs/hour/repository and 600/hour/account across +tabs, counting 304 responses too. Completed/hidden/paused/offline pages do not +poll. Manual Refresh obeys a 10-second per-target cooldown and the same budgets. +Tokenless public reads use no cookie/session scraping and gracefully exhaust. + +Rate-limit headers/Retry-After override schedules. Secondary limit/429/503 use +bounded delays of 60, 120 and 300 seconds with deterministic jitter injected in +tests; no unbounded retry or tight polling. A rate-limited session pauses related +targets until reset and shows the next permitted time. Browser suspension does +not need an alarm permission for ordinary page reads: resume/user activity schedules the next permitted +read from protected session timestamps. Missing/restarted state starts paused +until native identity is re-established. + +### 10.1.1 Explicit bounded background attention + +Ordinary hidden pages do not poll. An independently enabled alert monitor may use a browser alarm for at most five explicitly selected canonical targets, with optional alarms and, only for a supported OS channel, notifications grants. Chrome/Firefox can deliver basic OS notifications; Safari delivers toolbar/center attention items and never requests the unsupported notifications permission. The user chooses an available channel explicitly; denied/revoked grants stop that mode without silently changing channels. Default off; interval 5 minutes, allowed 5–60 minutes. One coalesced alarm per browser profile, at most six GET requests/wake and the same existing per-repository/account/concurrency/byte ceilings; overload rotates/defers targets and is visible. It never posts a command, invokes a model or expands to every repository. + +Revalidate current identity, grants, repository pause, source freshness and target on each wake. Persist only nonsecret scheduling preferences; private queued evidence/dedupe keys remain protected session data. Respect quiet hours and at most three alerts/10 minutes, 20/day. Browser/device sleep and alarm delivery can delay execution; never promise exact delivery or rely on cross-browser alarm persistence. Reconcile the one configured alarm after worker wake, clear it on disable and require reconnect before private monitoring after session loss. Partial/stale/unknown results generate an availability explanation, not a guessed transition alert. The seven explicit monitor cases in the catalog cover these boundaries. + +### 10.2 Failures and effects + +| Condition | Retained facts | Automatic behavior | User/operator action | +|---|---|---|---| +| 401/revoked token | Personal preferences only | Clear credential/private caches; stop reads | Reconnect intentionally | +| 403/404 private/masked | Public native view only | Mark denied/unknown, no broad fallback | Check selected repository/org access | +| Truncated pagination/oversize | Independently verified facts | Partial; no ready/zero aggregate | Open native sources | +| Head/base/ref/policy moved | Historical snapshot labeled | Discard current generation | Refresh current identity | +| Run pending/canceled/failed | Native facts and matching run link | Pending/failed/canceled, never complete | Inspect run; normal GitHub retry if desired | +| Card/pointer mismatch | Native state | Unavailable source | Maintainer reconciles existing card | +| Partial producer write | Successful source facts with time | No duplicate browser repair | Action replay reconciles publication | +| Offline/suspension | Session cache marked stale | Cancel work; bounded resume | Native browsing; reconnect if session lost | + +## 11. Security, permissions, and privacy + +### 11.1 Resolved authentication choice + +The complete product supports unauthenticated public reads and an **optional user-owned +fine-grained PAT** for selected repositories with Metadata, Contents, Issues, +Pull requests, Actions, Checks and Commit statuses **read** permissions as needed by the endpoint +inventory. This read profile requests no write, organization administration, workflow-write, Secrets or +bot workflow PAT; §11.3 defines the separately enabled optional write role. Connection UI explains why each read permission +is needed and allows remaining standalone. A credential lacking an optional read +capability makes that projection unavailable; it is not silently replaced with +a broader token type. Checks and Commit statuses are independent optional read +grants for the general CI tools, not prerequisites for reading the Copilot +projection. Fine-grained tokens support the selected Checks read endpoints in +§11.2; do not generalize this to write operations, Projects, +outside-collaborator or multi-organization scenarios. The Copilot assessment +panel uses the authoritative Action projection. The general CI tools may read +check/status facts directly under §11.2, without independently certifying +Copilot approval or overall merge readiness. + +Create the token in GitHub's native token settings; the extension neither creates +nor revokes it. Paste only in a trusted extension-origin connection view; never +in the page panel. Verify account via the authenticated native user read and +target access through the allowlisted endpoints. One active account/credential +per explicit operation; the local center supports at most five named session identities partitioned by host/user/role. Switching the active identity invalidates private evidence and requires a fresh target check. +Organization approval/SSO restrictions remain explicit unavailable states. + +Default storage is `storage.session`, not local/sync: content scripts have no +credential read message and default session exposure remains disabled; set +trusted-context access level where supported, without assuming Firefox provides +that API. Session is cleared on browser restart, disable/uninstall, disconnect +or detected revocation. D4 defines epochs/private browsing and suspension tests. +No browser connection has a remember-token option. Browser storage is not advertised as an +encrypted credential vault. + +OAuth app device flow was evaluated: it avoids an embedded secret but private +repository scopes are broader and introduces app registration/support. GitHub +App authentication offers selected permissions but requires installation/expiry +and refresh lifecycle. Defer both to a separately reviewed authentication slice; +no generic callback server or embedded client secret is introduced. PAT entry +is the selected portable least-privilege connection, with guided creation, clear role/scope verification and revocation help. User onboarding makes it understandable and optional. The complete product also supports independently enabled selected write-role sessions for the closed operations below; a read session never silently escalates. + +### 11.2 Endpoint and trust boundary inventory + +| Need | Allowed read family | Permission / constraint | +|---|---|---| +| Canonical identity/default ref | repository, branches/ref, commit metadata | Metadata/Contents read, exact repo and ref | +| Manifest | Contents at pinned commit | Contents read, fixed path ≤8 KiB | +| Source/status | issue/PR identity and exact conversation comments | Issues or Pull requests read; ≤3 pages/known comment | +| PR linkage/current revision | canonical pull and supported native association | Pull requests/Issues read; deny unknown association | +| Run/attempt/workflow source | Actions run/attempt metadata | Actions/Contents read; exact allowed workflow | +| General CI check facts | GET commits/{full-sha}/check-runs and check-runs/{numeric-id} | Optional Checks read; exact repo, head SHA and verified check identity | +| Selected check annotations | GET check-runs/{numeric-id}/annotations | Optional Checks read; verify parent repo/head before pagination | +| Commit status facts | GET commits/{full-sha}/status | Optional Commit statuses read; separate contexts from check-run conclusions | +| Finding destination | exact PR review/review-comment metadata | Pull requests read; exact repo/PR/comment | +| User identity/capability hint | authenticated user and repository permissions | No repository-admin request; absent permission stays unknown | + +These paths are fixed templates beneath the selected repository API root, not +caller-supplied URLs. The documented [check-run/annotation read endpoints](https://docs.github.com/en/rest/checks/runs#list-check-run-annotations) +support fine-grained PATs with Checks read; [combined commit status](https://docs.github.com/en/rest/commits/statuses#get-the-combined-status-for-a-specific-reference) +requires Commit statuses read (verified 2026-10-25). Public reads may be +unauthenticated under the same endpoint/identity/budget constraints. Request each +optional grant only for an explicitly enabled dependent feature; never obtain +Checks write, a classic PAT or administration permission to fill a missing row. + +BEX-CI-01/02/03 use those direct facts, loaded native check content and canonical +native destinations. The v1 Action projection supplies its assessment/findings +and source links; it does not promise arbitrary check annotations. Each general +CI view identifies its source and completeness separately from that projection. +Required/advisory classification needs current verified native requirement +evidence or a policy-bound Action classification; otherwise requiredness is +unknown, even when a check succeeds. An external check ID is never invented as +an Actions run/job ID. No direct check/status result grants approval or merge +authority. + +Use at most 100 items/page and three pages per selected check/annotation/status +collection, within the shared 12-GET/1-MiB refresh and hourly budgets. Remaining +pages are visibly partial and need an explicit budgeted continuation. Bind +annotations to the verified check's repository/full head SHA and preserve +unmapped lines as unplaced evidence. Missing/denied optional scopes, unsupported +access, unavailable policy or absent source data show the exact unavailable or +unknown state and native link; loaded native rows may remain with a loaded-only +label. Neither a denied source nor zero loaded rows means zero failures or a +complete annotation inventory. Source changes/revocation cancel and clear the +affected private evidence. CI01/CI03 catalog cases exercise enabled, denied, +partial, stale and moved-head paths under this contract. + +Each semantic request binds the numeric repository and a closed typed target to +the sender's current tab/account epoch. Conversation reads require exact +issue/PR identity; CI reads use a verified commit SHA, check ID or run/attempt +identity and never fabricate a conversation number for a standalone commit. +Separate named read operations validate their own target shape and parent +relationship before the adapter constructs an endpoint. No `{url,method,body}` +message exists. HTTPS exact GitHub/API origins +only; reject redirects to another origin before forwarding credentials. Do not +follow source-supplied URLs or retrieve raw artifacts/logs by default. All remote +text is bounded text, not `innerHTML`, selector input, executable code or command +template. Diagnostics redact tokens and private identifiers unless user explicitly +previews a minimal export under D6. No browsing history/code/drafts leave the +browser through extension-owned telemetry. + +### 11.3 Closed optional GitHub operations and setup separation + +The complete product includes explicit regular-label/assignee triage and selected run retry/cancel controls. These are not status reads or native command drafts. They use a separately selected user-owned write-role session and a closed semantic operation union; the read-role token is never silently promoted. Default off; grants are selected-repository Issues write or Actions write only as needed. Owner/maintain/push hints and provider authorization are both checked; neither a snapshot nor a browser feature grants authority. + +| Operation | Exact resource family | Required preflight/result | +|---|---|---| +| Add/remove regular labels | POST/DELETE canonical issue labels | Exact repo/object, current labels, selected delta and read-back; installed lifecycle/deploy labels excluded from this generic editor | +| Add/remove assignees | POST/DELETE canonical issue assignees | Current eligible assignees, explicit delta, exact scope and read-back | +| Retry failed run/jobs | POST exact run rerun-failed-jobs or exact job rerun | Workflow/run/attempt/job identity, actor grant and one explicit reviewed retry scope | +| Cancel active run | POST exact run cancel | Current active attempt and retained effects warning; canonical terminal observation | + +No arbitrary `{url,method,body}`, default-branch file edit, approval/merge/deploy request, credential/Secret mutation or generic workflow-input dispatcher is exposed. Every action creates a local immutable intent binding host/user/repo/object/current revision or value, operation/delta, expiry (maximum 60 seconds) and single-use nonce. Recheck before sending; a moved target invalidates consent. Maximum 20 explicitly selected bulk items, one sequential write at a time and per-item receipts. Never include unloaded pages or new selection after approval. + +Provider acknowledgement and observed result are separate. GitHub endpoints do not promise a universal idempotency key: timeout/uncertain submission enters unknown-outcome, performs bounded canonical reconciliation and requires explicit new review when ambiguity remains. Do not blindly retry a POST, claim zero effects, automatically roll back other actors' changes or reuse a consumed intent. Account/grant revocation or pause prevents new items while retaining already observed receipts. Export only redacted selected evidence. + +The local setup center uses the [shared setup companion](github-browser-extension-control-center-and-setup.md), not these GitHub write sessions. Setup credentials/provider keys and the legacy web Apply capability never enter extension storage or content messages. The CLI remains the installer/provider/permission/cleanup authority. Personal settings, repository runtime policy, Action state and installation plans have separate owners and persistence. + +## 12. Observability and operational UX + +Reader outcome codes: disabled, incompatible, no-source, partial-discovery, +untrusted-source, stale-identity, incomplete-evidence, access-denied, rate-limited, +offline and available. A source failure identifies the *failed read*, not a +false claim that the underlying Action work failed. The details view exposes +source links and observation time; sanitized local counters track request count, +cache hit, disposal and outcome without remote reporting. + +Action producer summary adds envelope schema/generation/source ID, bytes, +complete/partial publication and retryability. Secret values/raw payloads never +appear in logs. Existing idempotent publication/noise rules remain in force. + +## 13. Compatibility, migration, rollout, and rollback + +`statusSchemaMajor:1` and capability tokens are the public compatibility boundary; +Action semver is diagnostic, not sufficient capability detection. Unknown major +means C features unavailable; unknown capability is ignored as unsupported +without executing it. A producer changing fields/required enums must ship a new +major or explicitly negotiated capability with mixed-version fixtures. + +Order: shared contract/parser fixtures → additive Action publisher and manifest +support → pilot opt-in → extension C features → three-browser beta. Initially +the manifest is opt-in and human reviewed; setup/doctor additions are a separate +follow-up scope with existing owner SDDs updated then. Existing installations +with no manifest stay standalone; existing status readers ignore the added +hidden envelope. No historical comments need bulk migration. + +Producer replay upserts the existing card and repairs pointer after confirming +publication; if pointer write fails, the valid card remains inspectable and the +summary reports partial integration. A concurrent older publication cannot +overwrite newer generation/revision facts; use existing publication concurrency +and reread fences, not a browser mutex. Rollback disables manifest or C features +while preserving human status content and ordinary Action behavior. Retain v1 +reader support for one released extension major after a v2 producer appears; +deprecated support gets explicit user/operator notice, never silent reinterpretation. + +## 14. Testing strategy and numeric budget + +Owns bex-I-C01–bex-I-C16 (16 distinct cases) and integration portions of bex-A-C07–bex-A-C12, +bex-S-C01–bex-S-C16/bex-E-C08 in the retained **96-case core** inventory. The complete product requires **803** distinct cases: 96 core, 659 catalog feature cases and 48 center/setup integration cases. These owned subsets are not counted twice. +At least one strict parser positive/negative fixture per contract field family; +tests distinguish JSON schema, semantic consistency, provenance and final +freshness gates. Use deterministic fake GitHub adapters/clocks and replay/race +fixtures. All pure evidence/authorization policies need 100% branches; existing +repository coverage gates remain. No live credentials in fixtures. + +Required fixture set (delivered with implementation): valid issue/pending SDD, +valid PR/complete findings, missing manifest, future major, copied/untrusted +marker, malformed/duplicate-key JSON, foreign repo/comment, invalid SHA/count, +partial findings, changed head/base/policy, multiple PRs, failed run, source +pointer failure and out-of-order two-tab refresh. Every future runtime success fixture includes +the full native/run/configuration evidence required to prove it. The JSON examples +in this specification are structural illustrations and do not provide that proof. + +## 15. Documentation and discoverability + +Deliver product §15 `action-contract`, `permissions`, `configuration`, +`compatibility` and `troubleshooting` pages with native token setup, read-only +endpoint map, session expiry, org restrictions, schema examples, publication +order and no-Action behavior. Update existing command/status/publication docs +when producer/runtime support ships; preserve their existing ownership. Validate +links, schema examples and rendered states against the same fixtures. No user +docs may imply that this specification PR enables connected mode. + +## 16. Acceptance scenarios + +1. No reviewed manifest: remain standalone; no credential or Action request. +2. Correct source/actor/run/schema and final identity: render timestamped + assessment with exact native/source links; no independent merge permission. +3. Copied marker/actor login collision/foreign comment: reject before projection. +4. Any v1 SHA has length other than 40 lowercase hexadecimal characters: reject + the affected payload; exercise both short and overlong SHA fixtures. +5. Head/base/policy changes during collection: no satisfied/count fields survive. +6. Pagination/count/coverage incomplete: partial with unknown aggregate, not zero. +7. Run pending/canceled or source too old: pending/canceled/historical state; + Refresh only rereads and posts no status command. +8. Read credential denied/revoked: stop affected reads and clear protected data; + U features remain usable; no broader-scope fallback. +9. Prepare fix: require exact current same-repo PR review thread, matching finding + and supported command; otherwise provide safe copy-only/read-only guidance. +10. Duplicate refresh/submission generation: no extra comment, API mutation or + duplicate draft append. Action publication replay respects its existing card. +11. Roll back extension/producer: old/no manifest stays standalone and native + Action status remains readable; incompatible schema visibly unavailable. + +## 17. Requirements traceability + +| Requirement | Boundary | Test/evidence | Documentation | +|---|---|---|---| +| I1 | DiscoverCapabilities + trusted-ref adapter | bex-I-C01–bex-I-C03, bex-E-C07 | installation/action-contract | +| I2 | Closed parser/schema/semantic validator | bex-I-C03–bex-I-C04/bex-I-C13–bex-I-C15, valid/invalid fixtures | action-contract/compatibility | +| I3 | Source/run identity policy | bex-I-C05–bex-I-C06/bex-I-C09, bex-S-C06 | action-contract/security guidance | +| I4 | Existing projections + context VM | bex-I-C07–bex-I-C08/bex-I-C13–bex-I-C14, bex-V-C02–bex-V-C08 | features/troubleshooting | +| I5 | Collect/final-fence/page epoch policy | bex-I-C09–bex-I-C12/bex-I-C16, bex-N-C08–bex-N-C12 | compatibility/troubleshooting | +| I6 | GET adapter/request scheduler | bex-A-C07–bex-A-C12, bex-E-C04–bex-E-C06 | privacy/troubleshooting | +| I7 | SessionCredential and selected-repo reader | bex-S-C03–bex-S-C05/bex-S-C12–bex-S-C15 | permissions/privacy | +| I8 | DraftRequest/native composer | bex-V-C12–bex-V-C14, bex-S-C08, acceptance 9–10 | features/command guidance | +| I9 | Message/URL/text parsers | bex-S-C01–bex-S-C02/bex-S-C06–bex-S-C11/bex-S-C16 | architecture/privacy | +| I10 | Existing publisher + additive envelope | bex-I-C09/bex-I-C16, bex-E-C08–bex-E-C09, pointer/race replay fixtures | action-contract/upgrade | + +### I8 complete command-context rules + +The complete product offers the entire current documented command family, not only four starter drafts. All requests remain native drafts that a human reviews/submits; the Action applies its current admission/authorization/context rules. Commands are never synthesized from page prose or translated. + +| Command family | Native destination and guard | Effect/cost disclosure | +|---|---|---| +| help, status, sdd-diff, doctor, history | Exact supported issue/PR conversation | No model for these existing commands; publication/readiness/doctor/history remain distinct | +| plan, clarify, estimate, test-plan, explain, diagnose | Exact supported issue/PR conversation, explicit user-selected bounded prose | Potential configured agent execution and included data shown | +| analyze, review, findings, recheck | Exact canonical conversation/review target supported by the installed route | Review/model behavior follows current server contract; findings may run a fresh review | +| description | Exact supported PR conversation | May update PR description; preserves native draft before human submission | +| fix explicit IDs / all | Verified current same-repo authoritative PR review-thread reply, or separately advertised verified branch-scoped route | File-changing and actor-authorized; show selected IDs/all expansion and exact target | +| dismiss explicit IDs | Exact supported current finding context, same write-actor guard | Finding-state mutation even though no files change; rationale and scope preview | +| implement request | Authoritative verified branch-scoped route; review-thread branch is the supported default | File changes, scope and verification expectation; never an issue-only guessed PR | +| remember rule | Current verified PR or native issue-branch route only when advertised/accepted by the installed runtime | Persistent learned rule/file effect; user-authored prose, no imported page instruction | +| sync-branch with reviewed options | Verified issue/PR parent and working ref, under the installed synchronization contract | Dry-run/no-agent/source options; merge/fixer effects disclosed; Action owns mutation | + +Consumer routing is the intersection of its compiled known grammar, the reviewed installed route/capability catalog, verified native target and current actor capability hint. A producer declaration never grants authority. Unknown/unsupported routes show an exact reason and copy-only/native documentation fallback, without fabricating a command or an issue-to-PR association. The runtime rechecks actor, target, policy and revisions after human submission. Existing complete-command 2,000-character and structured-argument bounds remain; quote literal finding IDs through the canonical grammar and never build a shell command. + +The existing v1 status `commands` field remains its closed four-command compatibility subset. Full command discovery is additive: reviewed capability `command-drafts.v2` enables the fixed repository-relative `.copilot/browser-extension-requests.v2.json`, fetched at the same pinned default-branch commit as the manifest. The new [closed request schema](browser-extension/requests-v2.schema.json) and [complete example](browser-extension/examples/requests-v2.json) specify the 21 known command names, eligible context categories, write-actor/verified-branch requirements and effect/agent categories. Maximum 32 entries, 16 KiB, unique command names. IDs must match the canonical repository/manifest producer. A stale/malformed/extra-key or semantically broadened descriptor is unavailable. The example is structural and does not prove a deployed route or current viewer authority. + +The consumer validates every descriptor against its compiled safe matrix: it may narrow supported routes, never remove a required write/branch guard or introduce an unknown command. Conversation context for file-changing requests additionally requires the explicitly advertised branch-scoped route and current native linkage; generic issue comments remain insufficient. Old v1 consumers ignore the unknown v2 capability and retain compatible read/draft features. No field is added silently to a closed v1 object. Producer implementation/rollout and exact-context fixtures must accompany the compatible Action release. + +Release/hotfix creation uses enabled native Issue Forms with reviewed fields and human submission. Admission/start/deployment labels, approvals, workflow dispatch and merge/queue controls remain native/Action-owned handoffs with explicit effect/policy review. The complete local tower covers source cut, SDD, branch, PR, review, promotion, package/release publication, reconciliation and cleanup, retaining already completed effects after later failures. + +## 18. Implementation sequence + +1. Shared v1 schema, pure parser and complete provenance/freshness fixture set. +2. Additive existing-status producer/pointer, bounded bytes and publication fences; + update owning Action SDDs, tests and docs in the implementation PR. +3. Reviewed manifest and explicit connection/discovery, mixed-version tests. +4. Session credential and allowlisted read adapter, request budgets and error maps. +5. K1/K2 context/findings rendering, then K3 safe draft preparation. +6. Browser-loaded/security/race evidence, docs, operator pilot and rollback proof. + +## 19. Definition of Done + +Specification delivery: design/transport/authentication/ownership are decided, +examples and limits are internally consistent, links/catalog validate and review +is possible. Runtime implementation remains proposed. + +- [ ] I1–I10 have executable acceptance and traceability with the shared budget. +- [ ] Shared package/browser imports enforce read/draft/write/setup boundaries, exact intent validation and token-role isolation. +- [ ] Positive/negative schema/provenance/race/version fixtures pass. +- [ ] Source/identity/coverage/freshness states and EN/ES/FR/PT content match product UX. +- [ ] Authentication, session cleanup, API limits, replay and partial recovery pass. +- [ ] Producer changes update existing owning contracts/tests/docs together. +- [ ] Three real browser integration gates, docs and compatibility/rollback pass. +- [ ] Proposed/implemented/live evidence remain distinct in catalog and summaries. +- [ ] Specification generation/validation pass; no material decision remains open. + +## 20. References and decisions + +- [GitHub fine-grained token guidance](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens): selected repositories, organization restrictions and documented feature gaps; never assume all token families are equivalent. +- [Endpoint permission inventory](https://docs.github.com/en/rest/authentication/permissions-required-for-fine-grained-personal-access-tokens): verify each chosen read endpoint during implementation; unsupported reads are unavailable. +- [GitHub OAuth device flow](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps): evaluated alternative, an evaluated alternative requiring its own owned application/broker and release evidence. +- [GitHub App user tokens](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app): evaluated installation/expiry/permission tradeoff. +- [GitHub rate limits](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api): budget ceilings are product limits below provider allowances, not promises of provider availability. +- [GitHub API best practices](https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api): conditional reads, pagination and rate-limit recovery. +- [Session storage](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/session): cross-context lifecycle and default restricted exposure; browser adapter details in platform companion. + +Decision: passive API reads of one additive existing-status envelope; default-ref +trust; session-only optional fine-grained read token; current evidence separated +from human authorization. Alternatives rejected: DOM text as authority, +check names as proof, a status command on page load, remote backend requirement, +classic broad PAT fallback and embedding OAuth secrets. diff --git a/specs/github-browser-extension-control-center-and-setup.md b/specs/github-browser-extension-control-center-and-setup.md new file mode 100644 index 000000000..8fe32d113 --- /dev/null +++ b/specs/github-browser-extension-control-center-and-setup.md @@ -0,0 +1,341 @@ +# GitHub Extension — Local Control Center and Integrated Copilot Setup + +- Status: Ready for review — proposed complete product contract, unimplemented +- Date: 2026-10-25 +- Catalog capability ID: `github-browser-extension` +- Last verified: 2026-10-25, current setup source/spec inspection only +- Owners: Copilot product, setup, browser, security, accessibility and QA maintainers +- Scope: Packaged full-page configuration application plus shared setup presentation and explicit CLI-owned privileged setup handoff. +- Related issues/PRs: [Issue #694](https://github.com/vypdev/copilot/issues/694), [PR #699](https://github.com/vypdev/copilot/pull/699) +- Required review gates: product UX, setup parity, architecture, credential/loopback security, browser packaging, accessibility, tests and documentation +- Open decisions blocking design readiness: None. This specifies a new bounded adapter; current CLI/web behavior is not claimed to implement it. + +## 1. Executive summary + +The extension includes a full local application, opened in its own browser tab, with searchable features, personal profiles, repository connections, workspaces, Copilot operations, setup, activity, privacy and diagnostics. It loads from the signed extension package and supports local settings and setup-intent preparation offline. + +**Reuse decision:** extract browser-safe Svelte presentation, types, localization and pure setting/questionnaire validation from the existing setup into shared private modules. Keep the current CLI/application engine authoritative for repository inspection, credentials, permission probes, plans, writes and cleanup. The local center presents the complete shared journey; sensitive credential entry and final privileged approval take place in the paired existing same-origin local web authority page. A separate, newly designed broker may mirror sanitized state and submit nonsecret choices. It cannot proxy the existing web API or acquire Apply authority. + +```text +Toolbar or in-page Settings -> packaged local center -> configure personal features + -> choose Copilot repository -> prepare shared setup choices -> explicitly launch/pair CLI + -> nonsecret wizard/configuration in center -> protected credential/approval step in local web + -> CLI audits/applies/verifies -> redacted progress/result in center -> inspect/recover +``` + +Text equivalent: one setup engine has terminal, local web and extension presentations with explicit authority handoff; the browser feature does not become a second installer or a resident daemon requirement. + +## 2. Problem, current behavior, and evidence + +### Observed current behavior + +- `package.json` already uses Svelte 5, TypeScript and Vite for the local web setup assets. `web/src/session/setupCommandTransport.ts` posts to same-origin routes. +- `src/application/contracts/web_setup_view.ts`, setup use cases and pure policies define nonsecret views, questions, decisions, plans and provider boundaries. +- `src/cli/web_setup_bridge.ts` coordinates revisions, one controller, takeover, choices, progress and cancellation. It imports Node crypto and is not a browser-safe shared module. +- `src/cli/web_setup_server.ts` binds only 127.0.0.1 on an ephemeral port, checks Host and same-origin POST context, pairs with a terminal code and rejects cross-site requests. Its CSP contains frame-ancestors none and X-Frame-Options DENY. It is deliberately not an extension API or embeddable iframe. +- Existing setup/configuration SDDs require current plan approval, grant audit, exact scope, no secret-bearing view and cleanup-verified permission probes. Reading a panel does not grant write authority. + +The design must reuse these decisions while adding a separately reviewed presentation/transport adapter. Merely linking to the current web page is insufficient for the required local application; importing its Node bridge, embedding it in an iframe or loosening its CORS/origin checks is rejected. Runtime behavior and store/browser acceptance remain unknown until implementation. As-built reconstruction is not applicable. + +## 3. Actors, surfaces, and terminology + +| Actor | Goal | Surface | +|---|---|---| +| Individual developer | Configure personal GitHub experience | Packaged options application and toolbar | +| Repository maintainer | Inspect effective Copilot configuration and plan changes | Center Copilot/setup routes | +| Local setup operator | Supply credentials and approve exact privileged effects | Existing paired CLI/local web authority | +| Organization operator | Review inheritance/shared scope and batch plans | Shared setup flow, per-target previews/results | +| Maintainer/QA | Diagnose, prove parity and ship secure artifacts | Redacted receipts, shared fixtures, real browsers and docs | + +Personal settings are extension-owned preferences, not repository policy. A setup intent is nonsecret untrusted input, not a plan approval. An authoritative plan is produced by the CLI/application engine from current facts. A broker capability grants only its closed nonsecret view/edit operation set; it is not the web session key, a GitHub token or permission to Apply. Controller epoch binds the current view role and is revoked on takeover/expiry. + +## 4. Goals, non-goals, and fixed invariants + +| Requirement | Behavior | +|---|---| +| HUB-UI | Complete navigable packaged application with feature discovery, profile/permission/privacy management and accessible four-locale journeys. | +| HUB-TRANSPORT | Closed typed extension messages and opt-in exact-origin/session/target-bound CLI broker, with truthful fallback and one controller. | +| HUB-PLAN | Shared setup question/setting/plan/audit/apply semantics, exact scope, current single-use approval and independent result/cleanup evidence. | +| HUB-SECURITY | Setup/bot/provider secrets and legacy web capabilities remain in their current trusted authority; no arbitrary fetch, shell or policy bypass. | +| HUB-OPERATIONS | Reproducible shared packaging, migration, real browser/CLI parity, diagnostics, complete docs and rollback. | + +Required scope includes every CENTER and SETUP catalog row. No hosted service, user billing system, telemetry, localhost port scanner, arbitrary shell command, browser cookie scraping, default-branch write shortcut, hidden Action metadata editing or remote executable frontend. Native messaging may be evaluated as a separate transport with the same port contract; the complete product uses the bounded local broker plus a tested explicit native-web handoff when browser origin verification is unavailable. + +## 5. Current versus proposed product journey + +| Stage | Current | Required integrated product | +|---|---|---| +| Personal configuration | Small feature preferences | Full local application, search, profiles, permissions, privacy and recovery | +| Setup entry | Start terminal/local web | Repository confirmation and shared wizard/configuration inside center | +| No CLI | Existing installer unavailable | Useful local settings, complete nonsecret choices and explicit portable intent/handoff | +| Connect authority | Terminal prints local URL/code | Explicit user-started CLI session, identified target, code and permitted broker role | +| Sensitive step | Same-origin local web/terminal | The same protected authority step with clear return/progress in center | +| Apply | Existing engine audit/approval/write | Same engine and approval; no privileged broker shortcut | +| Result | Local web/terminal facts | Matching redacted center effects, partial cleanup and recovery links | + +```mermaid +sequenceDiagram + participant U as Operator + participant C as Packaged center + participant B as Extension background + participant L as Local nonsecret broker + participant E as Shared CLI engine + participant W as Trusted local web + U->>C: Choose repository and setup choices + U->>E: Explicitly start companion session + U->>C: Pair using terminal code + C->>B: Closed pair/edit intent + B->>L: Bound nonsecret request + L->>E: Validate current choices/revision + E-->>C: Redacted view and protected step required + U->>W: Enter secrets and approve current plan + W->>E: Existing authority/controller transaction + E-->>C: Observed progress and verified effects +``` + +Text equivalent: the center sends nonsecret intent through the background/broker; credentials and final approval remain in the trusted local web authority; one engine emits all progress and effects. + +## 6. Functional behavior and state model + +### Local application information architecture + +| Route | Required content and main action | +|---|---| +| Overview / My work | Selected scope, review/work queues, pending personal/setup actions and unavailable sources | +| Features | Search all 150 functions, problem/page filters, previews, default/effective state and why unavailable | +| Profiles | Named profile editor, inherited sources, full delta, import/export/migration/restore | +| Repositories / Workspaces | Explicit selected repositories, private retention, verified identities, pause/disconnect | +| Connections / Permissions | Active account per host, scoped read/write sessions, browser grants, revocation guidance | +| Copilot | Capability/context matrix, status/findings/commands, operational source links and configuration provenance | +| Setup / Configuration | Shared inspector, focused adjustments, full wizard, presets/batch, plan review, protected handoff and effects | +| Activity | Redacted intent/approval/acknowledgement/result distinction and user-invoked recovery | +| Privacy / Data | Retention, local/private state, export previews, per-scope clear/reset and authored-note protection | +| Diagnostics / Help / About | Per-feature health, compatibility, redacted export, complete docs, update/support and release identity | + +Use packaged history/hash routes with a closed route/parameter parser; no arbitrary return URL, secret, ref or command in a deep link. Toolbar, a visible GitHub Settings entry, shortcut and browser extension manager all open the same app through runtime.openOptionsPage or its target-specific equivalent. Popup is a quick launcher/status view, not the only configuration UI. Optional side panels are supplementary. + +Setup states: unpaired -> local-intent -> pairing -> inspecting -> editing -> review -> protected-authority -> checking -> applying -> verified/partial/blocked -> recovery/closed. Read-only observers and a single active controller have explicit roles. Expiry/disconnect never implies cancellation of already accepted effects. A local intent remains editable without a companion; importing it requires fresh authoritative validation and review. + +## 7. User-facing configuration + +| Setting | Default / allowed values | Scope and persistence | +|---|---|---| +| features | Packaged registered defaults; booleans per known ID | Global -> host/account -> organization -> repository, stored locally | +| active profile | Comfortable; choose among at most 10 named user profiles | Per host/account; complete diff before apply | +| workspace | Empty explicit selection; at most 20 repositories per workspace, 10 workspaces | Opaque IDs persistent; private metadata/session evidence expires on disconnect | +| locale | Browser-supported choice, fallback en; en/es/fr/pt | Personal setting, complete atomic message fallback | +| density / theme / motion | Comfortable / system / system; bounded documented alternatives | Personal; cannot remove required access/contrast | +| API connection | Off; at most five explicit named session identities | Partition host/user/repository/role; one chosen identity per operation | +| optional writes | Off; enable named supported write families independently | No inherited grant; live review per operation | +| alerts / quiet hours | Off; explicit supported channel and bounded monitor at 5–60 minutes for at most five selected targets; at most 3 per 10 minutes and 20/day, default quiet hours 22:00–08:00 local | Personal; Chrome/Firefox OS or local channel, Safari toolbar/center; no delivered-at guarantee during browser suspension | +| recents | Off; opt-in maximum 50 entries/7 days | Local extension activity only, no browser history permission | +| diagnostics | Off for collection beyond closed health reasons; maximum 200 redacted entries/7 days | User-controlled, private detail session-only | +| setup companion | Unpaired; manual exact local target/code | Broker capability session-only, no auto-discovery/reconnect | +| local note retention | Session | Persistent local authored content only after explicit opt-in; separate export/delete | + +Pause precedence is emergency > tab > repository > organization > host/account > global. Invalid or conflicting values preserve the prior complete revision; apply changes atomically and announce the result. Profiles/imports cannot request grants, approve writes or alter repository/Action safety. Global-only nonsecret export is recommended; adding repository rules or authored notes requires a separate readable disclosure. Unknown newer records remain inert/exportable. The 64 KiB imported setup-intent/settings limits and current pure validation are enforced before persistence. + +Recommended: local profile plus selected-repository read connection, writes/alerts/recents off, session notes and explicit CLI pairing when setup is needed. Alternative: maintainer profile with selected regular-label/run-retry write families and reviewed batch setup; every operation still needs its exact intent/grant/revision checks. + +## 8. Clean Architecture design + +### Reuse and package boundaries + +Proposed private `packages/setup-presentation` contains portable Svelte components, design tokens and four-locale presentation catalogs; the existing web entry and extension options entry consume it. Proposed private `packages/setup-contracts` exposes browser-safe immutable view/intent schemas and pure validation under explicit public barrels. Extraction must preserve current web/CLI behavior and keep root dependency overrides; no copied parallel questionnaire or magic imports of the full web application. + +Domain owns IDs, setting and approval invariants. Application owns InspectConfiguration, EditNonsecretSetupIntent, PreviewProfile, PairCompanion, ObserveSetup, HandoffProtectedStep and coordinator transitions through semantic ports. DOM/browser/GitHub/loopback/CLI implementations live in adapters; composition wires them. Presentation receives redacted view models and cannot call provider mutation, filesystem or shell APIs. The existing CLI remains the sole credential/provider/apply owner; server/Node modules are never browser shared code. + +```mermaid +flowchart LR + O[Packaged options entry] --> A[Center application and pure policies] + O --> UI[Shared setup presentation] + W[Existing local web entry] --> UI + UI --> V[Browser-safe view and intent contracts] + A --> P[Settings and companion semantic ports] + B[Validated background adapters] --> P + B --> T[Closed local broker transport] + T --> E[Existing setup application engine] + E --> G[Existing provider and workspace ports] + E --> S[Trusted web or terminal secret/approval adapter] +``` + +Text equivalent: two packaged browser entries reuse presentation/contracts; only the CLI engine reaches privileged provider/workspace adapters. Enforce transitive no-Node/no-provider imports in browser shared modules, no network/credential authority in presentation, closed package exports, cycle rules, component/module size budgets and exact registration parity. Changed shared components must pass both local-web and extension acceptance. + +### New nonsecret broker contract + +The following is a **proposed new protocol**, not an existing endpoint/flag. An explicitly launched CLI may open a separate 127.0.0.1-only ephemeral broker listener alongside the existing authority web server. Keeping separate listeners preserves all existing Host/origin/CSP/session guards. The broker accepts no reverse proxy, alias, forwarded host, arbitrary path, remote/LAN URL or redirect. The exact chosen authority/broker address, protocol and repository identity appear in CLI and center. No port scanning or page-supplied discovery. + +The operator supplies the extension origin displayed by the packaged center when explicitly launching this proposed broker mode. The CLI configures that exact origin before serving pairing or CORS preflight; it never learns an allowlisted origin from an unauthenticated network request. This is a new reviewed launcher contract, not an existing CLI flag. + +Pairing uses a separate single-use 128-bit terminal code expiring after 120 seconds, maximum five failures followed by 30-second cooldown. It establishes a 256-bit broker-only capability bound to exact extension origin/installation, repository, session and permitted observe/nonsecret-edit role. Check the real request origin and exact Host; no wildcard CORS or null/missing-origin exception. Unsupported origin behavior uses explicit existing local-web handoff. The broker capability is held only by the background session, never page/content scripts/URLs/exports. It cannot authenticate to legacy web routes, GitHub or any privileged Apply endpoint. + +Closed operations: pair, read redacted current state, answer an explicitly nonsecret question, request nonsecret Back/retry-discovery, request handoff to the trusted authority page, relinquish view control and disconnect. Each request binds protocol major, session ID, target identity, controller epoch, question/plan revision and monotonically increasing sequence/nonce. Request maximum 8 KiB, answer maximum 4,096 characters, redacted view maximum 256 KiB; no arbitrary URL/method/body/CLI command field. Unknown kinds/fields reject. Maximum two in-flight local reads; conditional foreground progress refresh at most once/2 seconds, idle once/10 seconds, stopped when hidden/unpaired. Broker idle expiry 30 minutes and hard expiry four hours never exceed its parent setup session. + +Credential, final plan approval, quick-edit approval and all provider/permission-probe/apply authority remain in the trusted terminal/local web role. Handoff rotates controller epoch; extension edits are read-only until a current explicit transfer back. Do not reuse an untyped answer route that could accidentally submit approve or a secret. The engine revalidates after every asynchronous boundary. A signed/native messaging adapter may later implement the same narrow port only after its target-specific install/packaging review; it does not become an arbitrary execution channel. + +## 9. UI/UX and content contract + +```text +Copilot · Configuration Repository: chosen/verified +Personal settings saved locally · GitHub not connected +[Features] [Profiles] [Repositories] [Copilot] [Setup] [Privacy] + +Setup: reviewed choices ready; no repository changes made +Next: connect the local setup companion to inspect current facts. +[Connect local companion] [Export nonsecret choices] [Read setup help] +``` + +```text +Protected setup step +Your exact plan is ready in the paired local setup page. +Credentials and final approval stay with the local CLI. +Completed: repository confirmed, choices validated, current plan inspected +Next: review the displayed plan and grants in that trusted page. +[Open protected step] [View plan here] [Cancel before new changes] +``` + +Pending: “Checking selected repository facts; no write authorized.” Action required: “Review this changed plan in the trusted local page.” Blocked: “Companion protocol incompatible; local preferences remain available.” Partial: “Two resources verified; one write outcome unknown; cleanup requires inspection.” Complete: “Selected effects read back; doctor result and actual Action execution evidence shown separately.” Offline: “Local features and intent planning ready; no remote facts certified.” Each state has one primary action and exact inspectable source/authority links. + +Use one page-level scroll, persistent understandable navigation, breadcrumbs and Back that preserve unsaved nonsecret choices. Route/page changes must not discard a form silently; show save/discard/cancel. Required warnings lead with user impact, then cause/action/retained state; raw IDs/logs stay expandable. Support keyboard, screen reader, EN/ES/FR/PT, dark/light/high contrast/reduced motion, 320 CSS px/200% zoom and long localized text. No nested scrolling plan pane, popup-only flow, surprise tabs or misleading current account. Protected handoff explicitly explains destination, purpose and return path. + +## 10. Failure, recovery, and cleanup + +No companion: offline intent or documented explicit CLI/web journey. Pair denial/expiry: show exact reason and current target, no silent retry loop. Browser/worker closed: reconcile canonical session state; do not resubmit an intent. Changed facts or controller: invalidate approval, retain choices and request fresh review. Permission or cleanup failure: preserve application/provider receipts and current cleanup journal. Uncertain effects: inspect/read back before retry; do not report rollback. Stop prevents subsequent effects under the existing engine contract. Disconnect clears broker/private cache and leaves applied resources and authored notes untouched. Closing an authority page is not proof that a CLI process stopped. + +## 11. Security, permissions, and privacy + +Browser origin is not GitHub authorization. The read/write browser account, one-run setup operator and bot/provider credentials are separate roles. Legacy web session keys and setup/bot/provider secrets never enter the extension background, message bus, browser storage, URL, plan intent, exported receipt or diagnostics. Only the new broker-only capability may live in protected background session memory; it is useless for privileged setup. A compromised content script cannot reach center-only ports or nominate a localhost target. Exact origins/Host, one-time pairing, role separation, nonsecret schemas, revision/epoch/nonce validation and current engine approval are independent defenses. Do not weaken existing server guards to make integration convenient. + +Persist only explicitly authored nonsecret settings; private repository names, evidence and session connection data stay partitioned and session-scoped. No analytics by default. Secret presence remains presence, not validity. Diagnostics export has a visible redaction preview and never includes complete request bodies or raw local filesystem paths by default. + +## 12. Observability and operational UX + +A session view reports current step, completed facts, current controller/role, next required human action, application effects, cleanup obligations and expiry. A redacted correlation joins CLI/web/extension observations but carries no credential. Report local setup file/resource success, permission-audit evidence, doctor readiness and actual deployed Action evidence as distinct dimensions. The center cannot overwrite an earlier accepted effect with a later generic failure. At most one current progress surface per session; no GitHub comment on every local refresh. + +## 13. Compatibility, migration, rollout, and rollback + +Version browser-safe contracts and broker protocol independently from the Action status schema. Unknown protocol major blocks the bridge and preserves local functionality; native handoff remains safe. Shared UI extraction preserves CLI flags/defaults and current local-web contracts. Setup intent is a versioned nonsecret input; unknown schema is inert/exportable, never an implicit approval. Native messaging has separate Chrome/Firefox host-manifest and Safari containing-app prerequisites and is not assumed equivalent. Every distributed artifact includes the same reviewed setup UI/catalog version. Rollback cannot reuse a newer broker/controller approval or erase unknown authored state. + +## 14. Testing strategy and numeric budget + +CENTER and SETUP feature cases are already counted in the functional catalog's **659** cases. The following **48 additional distinct cross-boundary cases** exercise shared UI, protected authority and broker/CLI interaction; none replaces a feature case or one of the 96 original core cases. Product total remains **803**, not a sum of browser matrix reruns. + +| Area | Minimum distinct cases | Behaviors/risks covered | +|---|---:|---| +| CTX | 8 | Cross-component ctx behavior with distinct concrete inputs and outcomes. | +| BRIDGE | 8 | Cross-component bridge behavior with distinct concrete inputs and outcomes. | +| PLAN | 8 | Cross-component plan behavior with distinct concrete inputs and outcomes. | +| SEC | 8 | Cross-component sec behavior with distinct concrete inputs and outcomes. | +| UX | 8 | Cross-component ux behavior with distinct concrete inputs and outcomes. | +| OPS | 8 | Cross-component ops behavior with distinct concrete inputs and outcomes. | +| Total | 48 | Independent integration boundaries, not copies of per-feature happy paths. | + +| Case ID | Area | Requirements | Scenario | +|---|---|---|---| +| bexhub-CTX-C01 | CTX | HUB-TRANSPORT | A content-script sender attempts to invoke a local-center settings or setup command: reject before reading private local state. | +| bexhub-CTX-C02 | CTX | HUB-TRANSPORT | A forged options-page URL or another extension ID sends a broker message: reject the sender and retain current state. | +| bexhub-CTX-C03 | CTX | HUB-TRANSPORT | An old control-center tab sends an edit after explicit takeover: reject its controller epoch and refresh it read-only. | +| bexhub-CTX-C04 | CTX | HUB-TRANSPORT | An account switch occurs while the options page is projecting a private repository: retire the old identity and require fresh connection. | +| bexhub-CTX-C05 | CTX | HUB-TRANSPORT | A local-center deep link contains a credential, arbitrary return URL or executable route: reject it without forwarding or logging the value. | +| bexhub-CTX-C06 | CTX | HUB-TRANSPORT | An oversized or extra-key message targets a privileged route: reject its closed schema before any provider or CLI call. | +| bexhub-CTX-C07 | CTX | HUB-TRANSPORT | A worker restarts during a nonsecret center navigation: restore committed preferences but require revalidation of any pending operation. | +| bexhub-CTX-C08 | CTX | HUB-TRANSPORT | The same setup session is open in native web and extension views: exactly one current role/controller can edit and handoff rotates authority. | +| bexhub-BRIDGE-C01 | BRIDGE | HUB-TRANSPORT | An ordinary GitHub page attempts broker pairing without the terminal code: reject its origin and create no session. | +| bexhub-BRIDGE-C02 | BRIDGE | HUB-TRANSPORT | A loopback redirect, LAN address, hostname alias or page-supplied port targets pairing: reject rather than forwarding the code or broker token. | +| bexhub-BRIDGE-C03 | BRIDGE | HUB-TRANSPORT | Five failed pairing codes occur within the window: apply the 30-second cooldown; expired or consumed codes cannot pair. | +| bexhub-BRIDGE-C04 | BRIDGE | HUB-TRANSPORT | A paired request uses the wrong repository, session, nonce or protocol major: reject before coordinator access. | +| bexhub-BRIDGE-C05 | BRIDGE | HUB-TRANSPORT | The background broker channel asks for a legacy web session key, PAT prompt answer or final Apply: reject the operation class. | +| bexhub-BRIDGE-C06 | BRIDGE | HUB-TRANSPORT | The CLI closes or reaches idle/hard expiry during foreground progress: mark disconnected, retain observed effects and require new pairing. | +| bexhub-BRIDGE-C07 | BRIDGE | HUB-TRANSPORT | A replayed broker edit uses an already consumed sequence/revision: return its prior acknowledgement or stale result without a new effect. | +| bexhub-BRIDGE-C08 | BRIDGE | HUB-TRANSPORT | A browser cannot establish the exact origin/host-permission handshake: use the explicit trusted local-web handoff and never relax CORS or origin checks. | +| bexhub-PLAN-C01 | PLAN | HUB-PLAN | A question changes after a nonsecret answer is drafted: require current revision review and do not submit the old answer. | +| bexhub-PLAN-C02 | PLAN | HUB-PLAN | Repository default SHA or remote configuration changes after plan review: the CLI invalidates approval and presents the changed plan. | +| bexhub-PLAN-C03 | PLAN | HUB-PLAN | A quick adjustment is requested for an unknown workflow expression: preserve inspection and route structural work through the full wizard. | +| bexhub-PLAN-C04 | PLAN | HUB-PLAN | The selected batch changes after per-repository plans are reviewed: require fresh aggregate approval bound to exact item identities. | +| bexhub-PLAN-C05 | PLAN | HUB-PLAN | A setup intent export is imported into another repository: treat it as untrusted choices and recompute the authoritative plan. | +| bexhub-PLAN-C06 | PLAN | HUB-PLAN | A permission probe succeeds but cleanup cannot be confirmed: retain the exact cleanup journal and report partial status in both views. | +| bexhub-PLAN-C07 | PLAN | HUB-PLAN | Stop is requested after one batch item applied: preserve that receipt and stop before new items rather than reporting a total cancellation. | +| bexhub-PLAN-C08 | PLAN | HUB-PLAN | A restored web tab tries to reuse a completed plan approval: the shared coordinator rejects the consumed approval before provider access. | +| bexhub-SEC-C01 | SEC | HUB-SECURITY | A setup credential is entered in the trusted same-origin authority page: no value appears in broker views/messages, extension storage or diagnostics. | +| bexhub-SEC-C02 | SEC | HUB-SECURITY | A selected-repository read session is passed as setup or bot authority: reject the credential role mismatch before any write. | +| bexhub-SEC-C03 | SEC | HUB-SECURITY | A profile import includes permission grants, commands or approval receipts: reject those fields atomically without enabling authority. | +| bexhub-SEC-C04 | SEC | HUB-SECURITY | A runtime Secret exists but cannot be validated: show presence-only evidence and never claim installed credentials are healthy. | +| bexhub-SEC-C05 | SEC | HUB-SECURITY | A setup state includes hostile markup or mention text: render escaped bounded text and no executable or auto-submitted instruction. | +| bexhub-SEC-C06 | SEC | HUB-SECURITY | A diagnostic export is requested with a private setup target: show a redaction preview and omit tokens, raw commands and absolute local paths by default. | +| bexhub-SEC-C07 | SEC | HUB-SECURITY | The broker receives forwarded-host headers or a DNS-rebinding Host mismatch: reject even when a pairing attempt is otherwise well formed. | +| bexhub-SEC-C08 | SEC | HUB-SECURITY | Disconnect occurs after a write intent is previewed: revoke the broker/controller capability and require a newly reviewed plan on reconnect. | +| bexhub-UX-C01 | UX | HUB-UI | A new user opens the local center offline: feature discovery, personal settings and nonsecret setup-intent planning remain usable. | +| bexhub-UX-C02 | UX | HUB-UI | A keyboard/screen-reader user navigates feature search, profile preview, setup handoff and back: focus and current step are announced without traps. | +| bexhub-UX-C03 | UX | HUB-UI | The center runs at 320 CSS px and 200% zoom with a long plan: primary controls stay reachable without fixed-height inner scrolling. | +| bexhub-UX-C04 | UX | HUB-UI | An English, Spanish, French or Portuguese setup journey falls back after one missing catalog entry: the whole affected message is coherent and literal IDs stay unchanged. | +| bexhub-UX-C05 | UX | HUB-UI | A feature preset changes twenty preferences: show a readable complete delta and retain the previous profile if validation or storage fails. | +| bexhub-UX-C06 | UX | HUB-UI | The protected setup step opens in a separate trusted tab: explain why, show the same session/target, and return to the exact center step after completion. | +| bexhub-UX-C07 | UX | HUB-UI | The local center closes mid-Apply: the CLI continues or stops according to its committed stage; reopening shows actual effects without resubmitting Apply. | +| bexhub-UX-C08 | UX | HUB-UI | A user clears diagnostics but retains authored notes: respect the explicit cleanup scopes and preserve the unrelated authored content. | +| bexhub-OPS-C01 | OPS | HUB-OPERATIONS | The packaged options application is installed without source files, Vite or a CLI: local routes/assets render entirely from the reviewed extension package. | +| bexhub-OPS-C02 | OPS | HUB-OPERATIONS | A shared setup presentation component is changed: CLI/web/extension fixtures still agree on questions, choices, permission explanations and plan semantics. | +| bexhub-OPS-C03 | OPS | HUB-OPERATIONS | A real Chrome worker terminates while displaying a paired setup result: reconnect shows canonical retained state and cannot revive an approval. | +| bexhub-OPS-C04 | OPS | HUB-OPERATIONS | A real Firefox event page unloads during a center workflow: protected state and session/controller rules behave identically after wakeup. | +| bexhub-OPS-C05 | OPS | HUB-OPERATIONS | A real Safari containing-app extension opens configuration and completes the supported setup handoff: no generic WebKit result substitutes for this evidence. | +| bexhub-OPS-C06 | OPS | HUB-OPERATIONS | A bundled extension shared-UI import reaches Node, provider mutation or filesystem code transitively: the architecture/build gate rejects the artifact. | +| bexhub-OPS-C07 | OPS | HUB-OPERATIONS | The companion CLI and extension protocol majors are incompatible: keep local settings available and show an exact supported upgrade/handoff path. | +| bexhub-OPS-C08 | OPS | HUB-OPERATIONS | A rollback restores a reviewed older extension while a newer setup intent exists: keep the unknown intent inert/exportable and never replay its approval. | + +Pure capability/epoch/approval/parser policies require 100% branch coverage; other new modules follow 95% statements/90% branches, with all changed executable lines covered and existing root thresholds retained. Use fake clocks, typed transports and provider fakes, corruption/replay/expiry/partial fixtures and semantic content assertions. Packaged CLI/web/extension shared-UI parity, actual Chrome/Firefox/Safari broker or documented authority handoff, EN/ES/FR/PT, real keyboard/screen-reader and privacy inspection are required acceptance evidence. A generic browser page does not prove extension or loopback handshake support. + +## 15. Documentation and discoverability + +Add local-center navigation, feature/profile examples, effective-setting provenance, connections/grants, privacy/retention/export/reset, shared setup full journey, protected handoff, command/CLI prerequisites, pairing/controller/expiry, batch/quick adjustment, credential roles, cleanup/replay and upgrade/rollback guides. Include an explicit statement that existing CLI/web works independently and which new adapter/flag is proposed rather than currently released. Link relevant context help from every unavailable/protected state. Contributor docs explain shared package exports, forbidden imports, fixtures, browser harnesses and secret-free diagnostic receipts. Register docs routes/assets/examples and validate all links. + +## 16. Acceptance scenarios + +1. Without a CLI/token, a user opens all local settings, discovers the full catalog, changes a bounded profile and prepares nonsecret setup choices. +2. With an explicitly started compatible CLI, the center confirms the same repository/session and participates in the shared nonsecret wizard. +3. Credential/final approval opens the trusted authority step; the center remains truthful and receives only sanitized progress/effects. +4. A stale approval, changed remote facts, takeover, expiry or duplicate intent cannot start new provider effects. +5. A failed/partial setup retains exact verified effects and cleanup obligations with a useful recovery action in both views. +6. All declared browser paths, four locales, accessibility, package/import rules and current CLI/web compatibility pass before acceptance. + +## 17. Requirements traceability + +| Requirement | Cases | +|---|---| +| HUB-UI | bexhub-UX-C01, bexhub-UX-C02, bexhub-UX-C03, bexhub-UX-C04, bexhub-UX-C05, bexhub-UX-C06, bexhub-UX-C07, bexhub-UX-C08 | +| HUB-TRANSPORT | bexhub-CTX-C01, bexhub-CTX-C02, bexhub-CTX-C03, bexhub-CTX-C04, bexhub-CTX-C05, bexhub-CTX-C06, bexhub-CTX-C07, bexhub-CTX-C08, bexhub-BRIDGE-C01, bexhub-BRIDGE-C02, bexhub-BRIDGE-C03, bexhub-BRIDGE-C04, bexhub-BRIDGE-C05, bexhub-BRIDGE-C06, bexhub-BRIDGE-C07, bexhub-BRIDGE-C08 | +| HUB-PLAN | bexhub-PLAN-C01, bexhub-PLAN-C02, bexhub-PLAN-C03, bexhub-PLAN-C04, bexhub-PLAN-C05, bexhub-PLAN-C06, bexhub-PLAN-C07, bexhub-PLAN-C08 | +| HUB-SECURITY | bexhub-SEC-C01, bexhub-SEC-C02, bexhub-SEC-C03, bexhub-SEC-C04, bexhub-SEC-C05, bexhub-SEC-C06, bexhub-SEC-C07, bexhub-SEC-C08 | +| HUB-OPERATIONS | bexhub-OPS-C01, bexhub-OPS-C02, bexhub-OPS-C03, bexhub-OPS-C04, bexhub-OPS-C05, bexhub-OPS-C06, bexhub-OPS-C07, bexhub-OPS-C08 | + +HUB-UI also maps to every CENTER feature case and UX docs; HUB-TRANSPORT to pairing/session use cases and architecture/permissions; HUB-PLAN to SETUP features and setup/recovery docs; HUB-SECURITY to credential-role/sender/intent policies and privacy docs; HUB-OPERATIONS to shared package/CLI/browser tests and release/contributor guidance. Functional catalog entries provide the exact additional per-feature case IDs. Existing setup SDDs retain ownership of installer policy and permission transactions. + +## 18. Implementation sequence + +1. Shared view/intent schemas and transport/application boundaries, proposed broker threat model, UX prototypes and fixtures. +2. Extract compatible setup presentation/locale modules; prove current CLI/web behavior and package parity before integrating the extension. +3. Build the complete local center and all feature/profile/privacy/connection routes. +4. Add offline intent planning/import and exact-repository validation through shared pure contracts. +5. Add the separate nonsecret broker and role/epoch-bound handoff while preserving the current authority server guards. +6. Integrate shared setup inspector/full wizard/quick edit/batch/doctor/progress and protected approval, then all failure/cleanup paths. +7. Complete real browser/accessibility/locale/security/performance and distribution/docs evidence across every required journey. + +These steps do not remove any registered setup or center function from final acceptance. + +## 19. Definition of Done + +- [ ] Every CENTER/SETUP feature and all 48 cross-boundary cases pass with source-linked evidence. +- [ ] Packaged local center is independently useful, searchable, accessible and complete in four locales. +- [ ] Shared UI/questionnaire/setting/plan/permission/cleanup parity passes CLI, web and extension fixtures. +- [ ] No Node/provider/credential authority enters browser shared packages or content scripts. +- [ ] Existing same-origin Host/CSP/pairing/session defenses remain intact; the new broker has only closed nonsecret operations. +- [ ] Current plan/controller/role and single-use approval fencing survive replay, takeover, expiry and partial outcomes. +- [ ] Actual target browser/OS paths, protected handoff, packaging and upgrade/rollback are verified. +- [ ] Documentation, help, routes, examples, privacy, diagnostics and recovery are complete and validated. +- [ ] No runtime/browser/provider/store acceptance is asserted from specification or fake-transport tests alone. + +## 20. References and decisions + +Owning current contracts: [local web setup](local-web-setup-assistant.md), [configuration management](setup-configuration-management.md), [setup/credentials/doctor](setup-configuration-credentials-and-doctor.md), [permission transactions](setup-pat-permission-guidance-and-verification.md), [batch setup](organization-configuration-reuse-and-batch-setup.md), [verification setup](verification-setup-onboarding.md). + +Primary platform evidence: [Chrome options](https://developer.chrome.com/docs/extensions/develop/ui/options-page), [Mozilla options](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Options_pages), [Chrome cross-origin requests](https://developer.chrome.com/docs/extensions/develop/concepts/network-requests), [Mozilla optional host permissions](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_host_permissions), [native messaging](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging). Inspected 2026-10-25; actual target behavior must be verified during implementation. + +Chosen: packaged full-page application, shared original Svelte UI/contracts, one setup authority, separate nonsecret broker, protected same-origin credential/Apply handoff and explicit offline intent. Rejected: iframe of current setup, importing Node bridge into a browser, generic fetch/shell proxy, broad CORS, broker-acquired legacy session/Apply credentials, a duplicate installer and an options popup that substitutes for the complete application. diff --git a/specs/github-browser-extension-functional-catalog.md b/specs/github-browser-extension-functional-catalog.md new file mode 100644 index 000000000..7a135c799 --- /dev/null +++ b/specs/github-browser-extension-functional-catalog.md @@ -0,0 +1,444 @@ +# Complete GitHub Extension — Functional Catalog and Product Acceptance + +- Status: Ready for review — complete proposed product contract; runtime unimplemented +- Date: 2026-10-25 +- Catalog capability ID: `github-browser-extension` +- Last verified: 2026-10-25, specification/schema review only +- Owners: Copilot product, architecture, security, accessibility, QA and documentation maintainers +- Scope: All 150 registered capabilities across 12 families, with mandatory acceptance on Chrome, Firefox and Safari desktop. +- Related issues/PRs: [Issue #694](https://github.com/vypdev/copilot/issues/694), [PR #699](https://github.com/vypdev/copilot/pull/699) +- Required review gates: product, architecture, security, accessibility, performance, testing, documentation, real browsers and release operations +- Open decisions blocking design readiness: None for this desktop github.com contract. Actual runtime/store evidence is required before product acceptance. + +## 1. Executive summary + +The extension is a complete daily GitHub productivity product: native page improvements, a local full-page control center, personal workspaces, Copilot automation tools and integrated setup. **Every row below is a required product capability.** Implementation waves organize dependencies; they cannot relabel required rows as optional future promises or accept a reduced feature set as the finished product. + +```text +Welcome and choose personal profile -> improve native GitHub -> configure local workspace + -> connect selected repositories if useful -> inspect verified Copilot context + -> prepare or explicitly authorize a supported operation -> inspect its result + -> configure Copilot through the shared setup journey -> diagnose and recover +``` + +The [product](github-browser-extension.md), [Action integration](github-browser-extension-action-integration.md), [platforms](github-browser-extension-platforms-and-delivery.md) and [control center/setup](github-browser-extension-control-center-and-setup.md) companions are normative. The [versioned feature catalog](browser-extension/feature-catalog.v1.json) is the authoritative structured inventory, not runtime implementation or evidence that tests ran. + +The catalog is a closed local index plus twelve family files in `browser-extension/features/`. Each fixed ID maps only to `features/.v1.json`; no remote reference, traversal, duplicate family or implicit directory discovery is allowed. The index schema and assembled catalog schema validate all parts, metadata and identities; every feature and case is retained in that assembled inventory. Each family file is limited to 96 KiB for reviewability. This partition addresses an observed GitHub comparison that omitted the former large single-file patch and correctly blocked the Action's progress assessment; it preserves complete evidence rather than exempting the catalog or weakening that gate. Publication verification must confirm patches exist for every changed file at the exact PR base/head. + +## 2. Problem, current behavior, and evidence + +The complete product must make a broad GitHub workflow understandable and dependable: comprehensive functions, excellent UX, reusable setup, enforceable architecture, proportional tests and complete documentation. This catalog defines that required scope while preserving the existing 96 core behavior cases and all provenance/authorization/native-preservation protections. + +Existing GitHub controls and current Copilot commands remain authoritative. An enhancement only mounts when it adds a useful workflow and does not duplicate an equivalent native control. Source baselines include the existing command reference, setup view/session contracts and the three original extension SDDs. No extension runtime or browser/store execution is claimed. Retrospective reconstruction is not applicable. + +## 3. Actors, surfaces, and terminology + +| Actor | Main journey | Surfaces | +|---|---|---| +| Developer | Read, navigate, search and organize work | Repository, code, lists, workspace | +| Reviewer/author | Understand changes and preserve review work | Diffs, threads, review drafts, checks | +| Maintainer | Triage, request automation and inspect delivery | Issues, Actions, releases, Copilot control tower | +| Setup operator | Inspect/configure repositories with reviewed authority | Packaged local center plus paired trusted CLI/web authority | +| Release/QA owner | Verify the complete product contract | Catalog, case inventory, artifact and human evidence receipts | + +Local is visible DOM/URL or personal settings; read is explicit canonical API evidence; draft prepares a native human-submitted request; write is a separately enabled reviewed GitHub mutation; setup delegates to the existing setup engine; monitor is an explicitly enabled, target-bounded subscription that revalidates authority on every scheduled wake. These are access boundaries, not commercial tiers. Premium describes quality/completeness and introduces no unrequested licensing, billing or hosted account. + +## 4. Goals, non-goals, and fixed invariants + +| Requirement | Behavior | +|---|---| +| CAT-NAV | Deliver every registered navigation and context capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-CODE | Deliver every registered code, files and diffs capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-REVIEW | Deliver every registered pull requests and reviews capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-ISSUE | Deliver every registered issues, discussions and collaboration capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-SEARCH | Deliver every registered search and personal views capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-NOTIFY | Deliver every registered notifications and attention capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-CI | Deliver every registered actions, checks and delivery evidence capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-RELEASE | Deliver every registered releases, tags and repository changes capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-WORK | Deliver every registered personal workspaces and platform ergonomics capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-COPILOT | Deliver every registered copilot action integration capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-CENTER | Deliver every registered local configuration and product experience capability with its access, boundaries, failure, UX and documentation contract. | +| CAT-SETUP | Deliver every registered integrated copilot setup and management capability with its access, boundaries, failure, UX and documentation contract. | + +All registered capabilities are required for general product acceptance. A user's missing permission, unavailable provider or unsupported repository configuration produces a tested unavailable state with an actionable native fallback, not a fabricated result. Optional permission means opt-in access, never an excuse to omit implementation. + +No page load submits comments or starts an agent. The browser never owns managed refs, hidden Action state, review policy, immutable release tags or setup approvals. No copied implementation/assets/product text, arbitrary scripts, remote executable patches, forced permission grants, broad-cookie access, telemetry by default or bypassed repository controls. Desktop github.com is the declared host/platform product; mobile and Enterprise compatibility need their separately verified host/API/store matrices and are not advertised implicitly. + +## 5. Current versus proposed product journey + +| Journey | Current limitation | Required product outcome | +|---|---|---| +| Native GitHub work | Repeated navigation and view decisions | Complete local/read workflows with reversible personal control | +| Review | Context spread across files, threads and checks | Revision-aware review workspace, drafts and evidence | +| Automation | Commands and lifecycle must be reconstructed | Current capability catalog, precise request preparation and trustworthy control tower | +| Configuration | Separate small options and setup tools | Full local center and shared setup presentation/engine | +| Failure | A failed feature can look like a failed repository | Isolated feature health, honest partial results and exact recovery | + +```mermaid +flowchart LR + C[Local control center] --> P[Personal profiles and workspaces] + P --> G[Native GitHub enhancements] + G --> A[Verified Action context] + A --> R[Reviewed request or explicit operation] + R --> E[Canonical result and recovery] + C --> S[Shared setup journey] + S --> E +``` + +Text equivalent: the local center configures personal GitHub use and shared setup; verified operations return inspectable results and recovery rather than an optimistic success state. + +## 6. Functional behavior and state model + +### Complete required capability inventory + +The following matrices are the readable projection of the JSON catalog. The nativeTarget field distinguishes a human text composer from a native control/form handoff; handoff cases verify preserved selection and native confirmation, not nonexistent comment-editor behavior. Each JSON entry also specifies activation, privacy, coexistence, accessibility, browser support, requirement owner, documentation and explicit test scenarios. Those fields and the mode contracts in §7 apply to every row. + +### Navigation and context (12 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-NAV-01 — Repository command palette | Repository pages: Open a searchable keyboard palette of native destinations, personal views and eligible Copilot tools. | page-local; available-with-eligible-page | Unsupported destinations are absent and native keyboard shortcuts keep precedence. | +| BEX-NAV-02 — Canonical object links | Issues, pull requests and commits: Copy the canonical URL with repository and object type preserved. | page-local; available-with-eligible-page | A same-number issue or unverified redirect cannot replace the observed target. | +| BEX-NAV-03 — Immutable line permalinks | Files and diffs: Copy an exact commit and selected line range, with a readable preview. | page-local; available-with-eligible-page | A moving branch or missing immutable revision disables permalink creation. | +| BEX-NAV-04 — Default branch and origin navigation | Repository, directory and fork pages: Jump to the observed default branch or verified upstream repository without losing the relative path when it exists. | page-local; available-with-eligible-page | Missing paths offer the repository root instead of an invented file. | +| BEX-NAV-05 — Branch and tag switch context | Files, branches and tags: Compare the current ref with a selected verified ref and preview file availability before switching. | selected-repository-read; explicit-opt-in | A deleted ref or incomplete ref listing cannot become the default branch implicitly. | +| BEX-NAV-06 — Compare direction controls | Compare pages: Swap known base and head with a preview that preserves explicit comparison semantics. | page-local; available-with-eligible-page | Cross-repository and three-dot comparisons retain their original repository identities. | +| BEX-NAV-07 — Issue, pull request and commit references | Conversations and rendered text: Make unambiguous observed object references navigable with accessible object-type labels. | page-local; available-with-eligible-page | Code samples, ambiguous identifiers and untrusted external hosts remain untouched. | +| BEX-NAV-08 — Contextual breadcrumbs | Deep file, review and workflow pages: Show compact breadcrumbs to repository, associated PR and source run only when verified. | page-local; available-with-eligible-page | Unknown associations remain explicitly unknown rather than guessed from a branch name. | +| BEX-NAV-09 — Copy names and paths | Repository, file and ref headers: Copy normalized repository name, ref, file path or qualified object identifier through explicit commands. | page-local; available-with-eligible-page | Clipboard denial exposes selectable text and preserves user selection. | +| BEX-NAV-10 — Context menus for selected references | Selected GitHub links and text: Offer opt-in browser context-menu actions for validated links, permalinks and opening the local control center. | page-local; available-with-eligible-page | Unrecognized selections and protected login pages receive no extension action. | +| BEX-NAV-11 — Personal location bookmarks | Repository and object pages: Pin an exact location in a named personal workspace with visibility and account scope shown. | personal-settings; explicit-opt-in | Private locations default to session retention and are excluded from ordinary settings export. | +| BEX-NAV-12 — Related object preview | Issue, PR, commit and workflow links: Show an opt-in bounded preview containing canonical identity, state and source time. | selected-repository-read; explicit-opt-in | Hover alone does not trigger unbounded reads and denied private previews reveal no cached title. | +### Code, files and diffs (14 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-CODE-01 — File tree and outline navigation | Files changed and code views: Navigate loaded file groups, symbols exposed by native GitHub and exact path search with visible loaded-scope counts. | page-local; available-with-eligible-page | Virtualized or unloaded files are labeled as a subset rather than silently omitted. | +| BEX-CODE-02 — Next and previous changed file | Pull request Files changed: Move among eligible files with a keyboard-accessible position indicator and return-to-origin action. | page-local; available-with-eligible-page | Disposed file anchors cannot receive focus after a soft navigation. | +| BEX-CODE-03 — Generated-file focus | Pull request diffs: Hide explicitly classified generated files with hidden counts and immediate restore. | page-local; available-with-eligible-page | Filename suffix alone never establishes generated status or hides a required finding. | +| BEX-CODE-04 — Whitespace and indentation readability | Code and diffs: Toggle visual whitespace markers, indentation guides and tab width without changing copied source. | page-local; available-with-eligible-page | Native code selection, line anchors and diff meaning remain intact. | +| BEX-CODE-05 — Readability and wrap profiles | Code, Markdown and diffs: Apply per-surface font size, line height, wrapping and density through bounded design tokens. | personal-settings; explicit-opt-in | Unsupported combinations retain horizontal access and never clip native controls. | +| BEX-CODE-06 — Copy patch and changed fragment | Diff hunks: Prepare a bounded patch or selected fragment with source revision and explicit inclusion preview. | page-local; available-with-eligible-page | Truncated or partially loaded hunks cannot be presented as the complete patch. | +| BEX-CODE-07 — Rename and binary context | Changed files: Explain verified rename relationships and binary or image changes with native source links. | selected-repository-read; explicit-opt-in | An unavailable blob or similarity estimate is not proof of identical content. | +| BEX-CODE-08 — File history and blame links | Code and diffs: Open native history or blame at the observed file/ref and preserve line context where supported. | page-local; available-with-eligible-page | A line that cannot be mapped opens the file with an explicit mapping limitation. | +| BEX-CODE-09 — Symbol and text navigation | Rendered code: Search loaded text and native symbol anchors with match counts and next/previous controls. | page-local; available-with-eligible-page | Search does not execute repository code or infer cross-file symbol resolution. | +| BEX-CODE-10 — Review progress markers | Pull request files: Track personal visited files against exact head/base identity and show what remains. | personal-settings; explicit-opt-in | A changed revision invalidates only affected progress and never alters GitHub review state. | +| BEX-CODE-11 — File type and path filters | Diff and directory lists: Combine extension, directory and text filters while exposing hidden content and reset. | page-local; available-with-eligible-page | Filtering cannot suppress native security or required-check blockers. | +| BEX-CODE-12 — Raw, rendered and download navigation | File headers: Offer native raw, rendered and download destinations with the exact source identity shown. | page-local; available-with-eligible-page | An executable download is never opened or run automatically. | +| BEX-CODE-13 — Dependency and configuration context | Manifests and lockfile changes: Link observed package names, version changes and configuration references to allowlisted native evidence. | selected-repository-read; explicit-opt-in | A package name alone cannot infer vulnerability status or fetch arbitrary registry URLs. | +| BEX-CODE-14 — Review checkpoints and return position | Long diffs: Resume an explicit per-revision review checkpoint with scroll and focused file context. | personal-settings; explicit-opt-in | A missing or rewritten file offers a safe fallback without inventing progress. | +### Pull requests and reviews (14 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-REVIEW-01 — Review readiness overview | Pull request header: Separate review requests, required checks, conflicts, queue state and Copilot assessment with source times. | selected-repository-read; explicit-opt-in | A successful advisory check cannot establish overall merge readiness. | +| BEX-REVIEW-02 — Finding and comment navigator | Pull request conversation and diffs: Navigate native comments and verified findings by file, severity, author and current state. | selected-repository-read; explicit-opt-in | Incomplete collection preserves unknown totals and historical findings stay labeled. | +| BEX-REVIEW-03 — Resolved and outdated thread controls | Review threads: Expand, collapse and restore selected thread categories while preserving editors and focus. | page-local; available-with-eligible-page | An active draft or unresolved required action cannot be silently hidden. | +| BEX-REVIEW-04 — Conversation event focus | Long issue and PR timelines: Focus comments, state changes, reviews or bot activity with visible hidden-event counts. | page-local; available-with-eligible-page | Filtered workflow failures remain discoverable through an explicit blocker indicator. | +| BEX-REVIEW-05 — Draft preservation and snippets | Native comment and review editors: Use local user-authored snippets with placeholder preview, append/keep/cancel and optional session drafts. | personal-settings; explicit-opt-in | No draft is sent to an agent or overwritten by a background refresh. | +| BEX-REVIEW-06 — Changed-since-review navigation | Updated pull requests: Compare a verified reviewed revision with the current head and open native comparisons. | selected-repository-read; explicit-opt-in | Force-pushed or unavailable commits show an unresolvable range instead of an empty diff. | +| BEX-REVIEW-07 — Requested reviewer context | Pull request sidebar: Explain requested versus submitted reviews and team-based requests from canonical facts. | selected-repository-read; explicit-opt-in | Team membership or reviewer presence cannot substitute for a current approval. | +| BEX-REVIEW-08 — Review submission preparation | Pull request review composer: Open the native review summary with selected comment, approve or request-changes intent for human review. | native-human-submission; explicit-opt-in | The extension never submits an approval or bypasses current repository review policy. | +| BEX-REVIEW-09 — Conflict explanation and recovery links | Conflicting pull requests: Show which native comparison or managed synchronization control can resolve the observed conflict. | selected-repository-read; explicit-opt-in | Unknown mergeability stays pending and no browser edit manufactures a managed branch. | +| BEX-REVIEW-10 — Merge and queue handoff | Pull request merge controls: Prepare a contextual handoff showing target, revision, merge method and queue/protection implications. | native-human-submission; explicit-opt-in | Unknown policy or a moved head blocks a claimed safe merge and returns to native GitHub. | +| BEX-REVIEW-11 — Task and checklist navigation | Descriptions and conversations: Index loaded checklist items and link back to their source without editing them. | page-local; available-with-eligible-page | Unchecked or partially loaded lists cannot be reported as complete. | +| BEX-REVIEW-12 — Change summary by ownership | Pull request overview: Group verified changed paths by directory and available CODEOWNERS evidence with completeness shown. | selected-repository-read; explicit-opt-in | Unparsed ownership rules remain unknown and never nominate an invented reviewer. | +| BEX-REVIEW-13 — Saved review filters | Review conversations and Files changed: Save personal author, state and path filters in a named profile with a visible active-filter summary. | personal-settings; explicit-opt-in | A shared URL or new account does not inherit another person's private review context. | +| BEX-REVIEW-14 — Review evidence export | Pull request overview: Export an explicitly selected redacted review receipt with exact revisions, sources and missing evidence. | selected-repository-read; explicit-opt-in | The export excludes tokens, private source text and unrelated review comments by default. | +### Issues, discussions and collaboration (12 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-ISSUE-01 — Issue triage summary | Issue header and lists: Show observed state, ownership, labels, milestone and next human action without inferring priority. | selected-repository-read; explicit-opt-in | Denied metadata cannot be displayed as unassigned or unlabeled. | +| BEX-ISSUE-02 — Structured issue drafting | Native issue forms: Prepare an installed issue form with explicit user answers and validation hints. | native-human-submission; explicit-opt-in | The extension does not silently replace an enabled form with a blank issue or submit it. | +| BEX-ISSUE-03 — Related issue and PR navigation | Issue and PR sidebars: Show native parent, sub-issue, dependency and closing-PR relationships when available. | selected-repository-read; explicit-opt-in | Textual mentions remain suggestions until the canonical relationship is verified. | +| BEX-ISSUE-04 — Label and assignee adjustments | Issue and PR triage controls: Preview and apply one explicit add/remove label or assignee change with current scope and read-back. | explicit-user-write; explicit-opt-in | Conflicting changes, missing write access and protected lifecycle labels route to native or Action-owned controls. | +| BEX-ISSUE-05 — Milestone and project handoff | Issue and PR sidebars: Open a verified milestone or project destination and prepare the selected native adjustment. | native-human-submission; explicit-opt-in | Unavailable Projects access does not trigger broader credential fallback. | +| BEX-ISSUE-06 — Duplicate and similarity research | Issue search and triage: Build explicit bounded searches from user-selected text and present source-linked candidate duplicates. | selected-repository-read; explicit-opt-in | Similarity is advisory and never closes or links an issue automatically. | +| BEX-ISSUE-07 — Conversation content navigation | Long issues and discussions: Navigate headings, decisions and loaded code blocks with source anchors and readable summaries of structure. | page-local; available-with-eligible-page | Structural navigation never claims an AI interpretation was reviewed by a maintainer. | +| BEX-ISSUE-08 — Personal issue annotations | Issue and PR context: Keep session-first personal notes and reminders with clear local/account ownership. | personal-settings; explicit-opt-in | Persistent local notes require explicit opt-in and are excluded from shared repository state. | +| BEX-ISSUE-09 — Cross-reference insertion | Native editors: Prepare canonical selected references as readable Markdown with a preview of the exact targets. | native-human-submission; explicit-opt-in | Untrusted text cannot inject an extra bot command, mention or hidden marker. | +| BEX-ISSUE-10 — Selected bulk triage | Issue and PR lists: Review an explicit bounded selection and per-item label/assignee changes, then execute with item receipts. | explicit-user-write; explicit-opt-in | Selection never extends to unloaded pages; partial success and uncertain items remain separate. | +| BEX-ISSUE-11 — Discussion and answer navigation | GitHub Discussions: Navigate loaded answers, categories and accepted-answer anchors while leaving moderation native. | page-local; available-with-eligible-page | An accepted answer is not inferred from reactions or comment ordering. | +| BEX-ISSUE-12 — Issue activity and dependency views | Issue overview: Show source-linked dependency blockers and chronological milestones from available native evidence. | selected-repository-read; explicit-opt-in | Circular, incomplete or inaccessible relationships are represented explicitly. | +### Search and personal views (8 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-SEARCH-01 — Named saved searches | GitHub search and lists: Save and restore an explicit query with host, account and repository scope. | personal-settings; explicit-opt-in | Opening a shared query never silently replaces it with a personal default. | +| BEX-SEARCH-02 — Search query builder | Search controls: Build supported native qualifiers through readable chips and preview the exact query. | page-local; available-with-eligible-page | Unsupported qualifiers remain editable text and are not represented as validated filters. | +| BEX-SEARCH-03 — In-page loaded-result filtering | Search and repository lists: Filter already loaded results by visible properties with local-versus-server scope explained. | page-local; available-with-eligible-page | Local filtering cannot claim it searched unseen pages. | +| BEX-SEARCH-04 — Cross-repository work searches | Local workspace: Run explicit bounded saved searches across selected repositories with per-repository completeness. | selected-repository-read; explicit-opt-in | Denied repositories stay unavailable instead of disappearing from the result summary. | +| BEX-SEARCH-05 — Result provenance and completeness | Search results: Show repository/object identity, observation time and pagination/truncation alongside result counts. | selected-repository-read; explicit-opt-in | An exhausted budget cannot be shown as a complete zero-result search. | +| BEX-SEARCH-06 — Recent local navigation | Control center and command palette: Offer opt-in extension-local recent destinations with bounded retention and clear/delete controls. | personal-settings; explicit-opt-in | No browser history permission or background browsing-history collection is used. | +| BEX-SEARCH-07 — Search-to-workspace collections | Search results: Pin selected canonical results to an account-scoped personal collection with explicit privacy choice. | personal-settings; explicit-opt-in | Unloaded results and private titles are not copied into persistent collections implicitly. | +| BEX-SEARCH-08 — Accessible result traversal | Search and lists: Move among visible results with stable focus, position announcements and return links. | page-local; available-with-eligible-page | Native text input and browser find retain their normal keyboard behavior. | +### Notifications and attention (8 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-NOTIFY-01 — Loaded inbox grouping | Native notifications page: Group visible notifications by repository, reason and object type without API credentials. | page-local; available-with-eligible-page | The group count is explicitly limited to loaded notifications. | +| BEX-NOTIFY-02 — Notification source previews | Native notifications list: Show observed source state and source links beside the native notification entry. | page-local; available-with-eligible-page | Private content absent from the current page is not fetched with a classic token fallback. | +| BEX-NOTIFY-03 — Explicit notification selection | Native notifications page: Select loaded notifications by visible reason/state and preview the exact set before native actions. | page-local; available-with-eligible-page | Selection never includes unloaded notifications or executes a destructive action on page open. | +| BEX-NOTIFY-04 — Mark-read and unsubscribe handoff | Native notification controls: Focus the native mark-read, done or unsubscribe action for the reviewed selection. | native-human-submission; explicit-opt-in | The official notification API's classic-token requirement never silently broadens access. | +| BEX-NOTIFY-05 — Personal snooze and reminders | Workspace attention queue: Snooze a personal reference until a chosen local time and show its local-only status. | personal-settings; explicit-opt-in | Snoozing does not change GitHub subscription or guarantee a background notification delivery time. | +| BEX-NOTIFY-06 — Optional attention alerts | Extension toolbar/local center; OS notifications on Chrome/Firefox: Enable bounded opt-in alerts for explicitly tracked verified transitions with quiet hours and deduplication. | explicit-bounded-alert-monitor; explicit-opt-in | Safari uses the accessible local channel; denied/unsupported channels, suspension and missing evidence never create repeated prompts or guessed alerts. | +| BEX-NOTIFY-07 — Mentions and review attention views | Native inbox and visible lists: Focus visible direct mentions and review requests while preserving access to all hidden categories. | page-local; available-with-eligible-page | A matching string alone cannot classify a private team mention or authoritative review request. | +| BEX-NOTIFY-08 — Notification privacy and lifecycle | Control center privacy page: Inspect and clear local attention state with retention, quiet-hours and account isolation controls. | personal-settings; explicit-opt-in | Disconnect removes private cached evidence while preserving explicitly authored nonsecret settings. | +### Actions, checks and delivery evidence (10 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-CI-01 — Check hierarchy overview | Pull request and commit checks: Show canonical check/status outcomes; classify required/advisory only with current requirement evidence, otherwise unknown. | selected-repository-read; explicit-opt-in | Checks/Commit statuses read are optional feature grants; denied or partial sources never become zero failures, and skipped legs never count as successful required evidence. | +| BEX-CI-02 — Run and attempt navigation | Actions and PR checks: Navigate the exact workflow run, attempt, job and annotation referenced by a result. | selected-repository-read; explicit-opt-in | A later attempt cannot silently replace the source of an older finding. | +| BEX-CI-03 — Annotation navigator | Check output and changed files: Group annotations from the verified Checks read endpoint by file/severity with exact line/revision mapping. | selected-repository-read; explicit-opt-in | Missing Checks read shows unavailable/native loaded-only fallback; unmapped or truncated annotations remain explicit partial/unplaced evidence. | +| BEX-CI-04 — Failure comparison | Workflow run history: Compare selected attempts' observed outcomes and changed failure locations. | selected-repository-read; explicit-opt-in | The extension does not diagnose causation from a single timing correlation. | +| BEX-CI-05 — Run retry controls | Workflow run or failed job: Preview exact repository, workflow, run/attempt and failed-job scope, then request one supported retry. | explicit-user-write; explicit-opt-in | An uncertain response is reconciled through canonical run state before any repeated request. | +| BEX-CI-06 — Run cancellation controls | Active workflow run: Confirm the exact running attempt and explain retained side effects before cancellation. | explicit-user-write; explicit-opt-in | A completed or replaced attempt invalidates the confirmation rather than cancelling another run. | +| BEX-CI-07 — Workflow dispatch preparation | Actions workflow page: Prepare a reviewed native workflow-dispatch form with exact ref and supported inputs. | native-human-submission; explicit-opt-in | Hidden inputs, deployment policy and unknown workflow identity block an invented execution route. | +| BEX-CI-08 — Artifacts and job summaries | Workflow runs: Navigate verified summaries and user-selected artifacts with size/type/source preview. | selected-repository-read; explicit-opt-in | Expired artifacts or redirected downloads never receive an unrelated credential. | +| BEX-CI-09 — Queue, runner and waiting explanations | Run and PR status: Distinguish queued, waiting for environment approval, running and unavailable runner evidence. | selected-repository-read; explicit-opt-in | Unavailable runner permissions cannot be converted into zero capacity or a failed workflow. | +| BEX-CI-10 — Performance and reliability trends | Selected workflow history: Summarize a bounded explicit run sample with percentile, cancellation and missing-sample disclosure. | selected-repository-read; explicit-opt-in | Sampling bias and incomplete history prevent claims about repository-wide reliability. | +### Releases, tags and repository changes (8 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-RELEASE-01 — Release and tag navigation | Merged PRs, tags and releases: Navigate verified native release/tag destinations and preserve immutable source links. | page-local; available-with-eligible-page | A merge date alone cannot associate a PR with a release. | +| BEX-RELEASE-02 — Release comparison builder | Releases and compare pages: Prepare comparisons between selected existing tags and disclose unavailable refs. | selected-repository-read; explicit-opt-in | A missing tag is not substituted with a similarly named branch. | +| BEX-RELEASE-03 — Unreleased change inspection | Repository overview: Show a bounded comparison of the default branch and a selected verified release tag. | selected-repository-read; explicit-opt-in | The view labels its chosen baseline instead of claiming a universal latest-release definition. | +| BEX-RELEASE-04 — Changelog drafting | Native release editor: Prepare user-reviewed Markdown from explicitly selected linked PRs and commits with source attribution. | native-human-submission; explicit-opt-in | The extension does not publish a release or claim every change was collected. | +| BEX-RELEASE-05 — Release asset verification context | Release assets: Show published checksums/signature/provenance links that actually exist for the selected asset. | selected-repository-read; explicit-opt-in | A checksum without an authenticated source is not labeled as a trusted signature. | +| BEX-RELEASE-06 — Dependency and security navigation | Dependency and security pages: Link native dependency, advisory and update surfaces with available permissions shown. | page-local; available-with-eligible-page | Private security alerts are not scraped from unrelated pages or exported by default. | +| BEX-RELEASE-07 — Branch comparison workspace | Branches and compare pages: Compare explicitly selected branches with ahead/behind and ancestry facts from canonical data. | selected-repository-read; explicit-opt-in | Divergence is not described as safely deletable or automatically reconcilable. | +| BEX-RELEASE-08 — Release activity attention | Workspace release views: Track selected release or tag links through explicit foreground refresh and optional alerts. | personal-settings; explicit-opt-in | No background repository-wide polling or automatic package execution occurs. | +### Personal workspaces and platform ergonomics (8 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-WORK-01 — My work overview | Local control center: Aggregate explicit selected assigned issues, authored PRs and review requests with per-source completeness. | selected-repository-read; explicit-opt-in | The default scope never expands to every private organization repository. | +| BEX-WORK-02 — Named repository workspaces | Control center: Create bounded personal workspace collections and switch context without changing repository policy. | personal-settings; explicit-opt-in | Private membership and metadata remain account-partitioned and excluded from ordinary exports. | +| BEX-WORK-03 — Work queues and next actions | Control center: Arrange personal reading/review/maintenance queues with source-linked next actions. | personal-settings; explicit-opt-in | Personal order cannot masquerade as a shared repository priority or SLA. | +| BEX-WORK-04 — Context-preserving split navigation | GitHub links and command palette: Offer explicit open-in-current or new-tab actions while preserving native browser behavior. | page-local; available-with-eligible-page | The extension never scans all open tabs or steals focus from another application. | +| BEX-WORK-05 — View and reading profiles | All supported GitHub pages: Switch bounded named comfortable, compact and review profiles with a preview of changed features. | personal-settings; explicit-opt-in | Profiles cannot grant permissions or hide required native actions. | +| BEX-WORK-06 — Local draft and session workspace | Control center: Inspect explicitly saved session snippets, notes and pending drafts with deletion and export choices. | personal-settings; explicit-opt-in | Disconnect cannot publish a draft or silently delete an explicitly persisted authored note. | +| BEX-WORK-07 — Unavailable capability explanations | Every feature entry point: Explain missing permission, producer, source, browser API or page support with one useful recovery action. | page-local; available-with-eligible-page | The UI never implies a feature is complete merely because a button rendered. | +| BEX-WORK-08 — Upgrade and compatibility center | Control center: Show extension, Action contract, setup companion and browser compatibility with exact sources. | selected-repository-read; explicit-opt-in | Unknown versions remain unknown and no release asset is executed automatically. | +### Copilot Action integration (24 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-COPILOT-01 — Issue-to-release control tower | Issue, PR and control center: Show verified issue, SDD, branch, PR, run, promotion, publication and reconciliation links in one journey. | selected-repository-read; explicit-opt-in | Partial publication remains published even if later synchronization fails. | +| BEX-COPILOT-02 — SDD question workbench | Issue clarification card: Prepare numbered answers for the current verified questions with owner and revision context. | native-human-submission; explicit-opt-in | A changed question round invalidates prepared answers rather than submitting stale decisions. | +| BEX-COPILOT-03 — SDD publication comparison | Issue and PR SDD panel: Prepare the supported sdd-diff request and open verified first/current publications. | native-human-submission; explicit-opt-in | Unavailable historical evidence cannot be inferred from a filename or an unverified comment. | +| BEX-COPILOT-04 — Issue admission and start guidance | Installed issue forms and issue sidebar: Guide enabled issue-kind forms and the native in-progress transition with the Action as branch owner. | native-human-submission; explicit-opt-in | The extension never creates, renames or deletes an Action-managed branch. | +| BEX-COPILOT-05 — Plan, clarify and estimate requests | Supported issue or PR conversation: Prepare the selected plan, clarify or estimate command with explicit request text and context. | native-human-submission; explicit-opt-in | A read-oriented command's possible agent cost is shown before human submission. | +| BEX-COPILOT-06 — Explain, diagnose and test-plan requests | Supported issue or PR conversation: Prepare explain, diagnose or test-plan for the user's selected bounded context. | native-human-submission; explicit-opt-in | Selected private code is not transmitted until the user explicitly includes and submits it. | +| BEX-COPILOT-07 — Analysis and review requests | Supported conversations: Prepare analyze, review, findings or recheck with the exact target and expected review effect. | native-human-submission; explicit-opt-in | Findings reconciliation is not falsely described as always model-free. | +| BEX-COPILOT-08 — Finding state navigator | Pull request findings: Show open, fixed, obsolete, dismissed, reopened, verification and unknown states with current coverage. | selected-repository-read; explicit-opt-in | A resolved native thread alone cannot prove a finding was fixed. | +| BEX-COPILOT-09 — Targeted finding corrections | Authoritative PR review thread or verified branch-scoped route: Prepare fix for explicit verified finding IDs and show the exact branch/revision that the Action will recheck. | native-human-submission; explicit-opt-in | Unknown or foreign-fork write authority gives copy-only guidance instead of a guessed target. | +| BEX-COPILOT-10 — Finding dismissal preparation | Supported current finding context: Prepare dismiss for selected current IDs with explicit rationale and scope. | native-human-submission; explicit-opt-in | Dismissal remains a state-changing authorized request even though it changes no files. | +| BEX-COPILOT-11 — Implementation requests | Supported authoritative branch-scoped context: Prepare a concrete implementation request with explicit scope, branch, revision and verification expectations. | native-human-submission; explicit-opt-in | An issue-only context without an authoritative branch route cannot invent a write target. | +| BEX-COPILOT-12 — Learned rule preparation | Verified current PR or native issue branch route: Prepare remember with user-authored rule text, affected repository file and persistent-effect warning. | native-human-submission; explicit-opt-in | Untrusted page instructions cannot become a persistent learned rule without explicit human review. | +| BEX-COPILOT-13 — Branch synchronization workbench | Verified issue or PR branch context: Prepare sync-branch with reviewed dry-run, no-agent and optional verified source choices. | native-human-submission; explicit-opt-in | The source is selected from authoritative refs and cannot be injected through page prose. | +| BEX-COPILOT-14 — Runtime doctor and health | Issue, PR and setup center: Prepare doctor and distinguish credential presence, runtime readiness and actual execution evidence. | native-human-submission; explicit-opt-in | A read-only doctor result cannot certify write permissions or runner authentication. | +| BEX-COPILOT-15 — Request history and receipts | Supported conversation: Prepare history and navigate current supported request receipts with correlation and source identity. | native-human-submission; explicit-opt-in | Missing receipts do not imply an empty history or a failed execution. | +| BEX-COPILOT-16 — PR description and help | Supported PR conversation: Prepare description or help with the installed capability and potential PR-body effect explained. | native-human-submission; explicit-opt-in | Description refresh cannot overwrite a native draft without an explicit operator decision. | +| BEX-COPILOT-17 — Approval and blocker explanation | Pull request status: Explain current review, check, finding, policy and branch-sync blockers with source links. | selected-repository-read; explicit-opt-in | The extension never grants approval or converts unknown-producer checks into verified checks. | +| BEX-COPILOT-18 — Queue and concurrency view | Copilot runs and control center: Show durable lifecycle, temporary activity and human waiting as independent facts. | selected-repository-read; explicit-opt-in | An old agent label cannot prove a current active run or permanently block a page feature. | +| BEX-COPILOT-19 — Release and hotfix launch guidance | Installed release and hotfix issue forms: Prepare the appropriate native form with version, origin and production-first consequences for human submission. | native-human-submission; explicit-opt-in | The extension never silently creates a release issue or selects an unverified version tag. | +| BEX-COPILOT-20 — Deployment review handoff | Verified deployment control center: Show publication state, intended deploy-label or native approval action, modes and retained effects before opening the exact native control. | native-human-submission; explicit-opt-in | Unknown deployment policy blocks an asserted safe launch; page opening never deploys. | +| BEX-COPILOT-21 — Reconciliation and recovery view | Deployment issue and promotion/reconciliation PRs: Separate published artifacts, pending development targets, cleanup and permitted recovery operations. | selected-repository-read; explicit-opt-in | Immutable tags, unknown lineage and nonretryable blocks are never repaired by browser metadata edits. | +| BEX-COPILOT-22 — Policy and configuration provenance | Copilot panel and settings: Show versioned workflow/input/Variable scope and source-time policy limitations with exact links. | selected-repository-read; explicit-opt-in | Secret existence is presence only; hidden effective values remain unknown. | +| BEX-COPILOT-23 — Run, cost and evidence inspection | Copilot history and job summaries: Present published duration, usage/cost and verification artifacts only when the producer supplies them. | selected-repository-read; explicit-opt-in | Missing usage is unknown, never zero, and no billing value is inferred from a model name. | +| BEX-COPILOT-24 — Capability and command compatibility | Control center and every Copilot action: Show the installed supported command/context matrix and explain unavailable product actions. | selected-repository-read; explicit-opt-in | An unknown Action version cannot receive a newly invented command syntax or event route. | +### Local configuration and product experience (14 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-CENTER-01 — Full-page local control center | Packaged extension options page: Open a navigable application with overview, features, profiles, repositories, Copilot, setup, activity, privacy and help. | personal-settings; available-on-local-center | The page loads from the extension package and remains useful offline without a CLI. | +| BEX-CENTER-02 — Feature catalog and previews | Features route: Search, filter and preview every registered feature by surface, capability, permission, state and profile. | personal-settings; available-on-local-center | A disabled feature explains its reason and cannot be silently enabled by a remote publication. | +| BEX-CENTER-03 — Profile editor and inheritance | Profiles route: Preview global, host/account, organization, repository and session overrides with provenance and reset. | personal-settings; available-on-local-center | An unknown imported field or invalid cross-field combination leaves the previous complete profile intact. | +| BEX-CENTER-04 — Repository connection manager | Repositories route: Connect, pause, switch and remove explicitly selected repositories with account/source identity shown. | personal-settings; available-on-local-center | A repository rename uses its verified numeric identity and cannot expose a different private repository. | +| BEX-CENTER-05 — Account and credential roles | Connections route: Manage at most five named session identities with separate selected-repository read and optional write roles. | personal-settings; available-on-local-center | Switching identity invalidates private evidence and never reuses a token across hosts or purposes. | +| BEX-CENTER-06 — Permission and privacy inspector | Privacy route: Explain each browser/GitHub/CLI capability, granted scope, retention and revocation path. | personal-settings; available-on-local-center | Unknown permission is displayed as unknown and optional capabilities stay off until granted. | +| BEX-CENTER-07 — Shortcuts and command customization | Shortcuts route: Configure bounded bindings and favorites with native/OS conflict detection and reset. | personal-settings; available-on-local-center | Editing shortcuts cannot capture secrets, typing composition or protected login interactions. | +| BEX-CENTER-08 — Settings backup and restore | Data route: Preview, validate and atomically import/export versioned nonsecret settings with migration and rollback. | personal-settings; available-on-local-center | Private evidence, credentials and setup approval receipts are excluded from settings exports. | +| BEX-CENTER-09 — Local operation activity | Activity route: Inspect redacted operation intent, exact target, acknowledgement and observed completion separately. | personal-settings; available-on-local-center | A timeout is unknown outcome and cannot be replaced by a fabricated success record. | +| BEX-CENTER-10 — Feature diagnostics and recovery | Diagnostics route: Identify broken adapters, missing permissions and stale versions; disable one feature or reset owned state. | personal-settings; available-on-local-center | Diagnostics never collect private code, tokens or full browsing history automatically. | +| BEX-CENTER-11 — Appearance and accessibility preferences | Appearance route: Configure themes, density, readable text, reduced motion and contrast through accessible bounded controls. | personal-settings; available-on-local-center | A setting cannot lower required contrast or remove keyboard access to a core action. | +| BEX-CENTER-12 — Language and terminology | Language route: Provide complete English, Spanish, French and Portuguese with atomic fallback and separate Action-source language. | personal-settings; available-on-local-center | A missing message cannot produce a partly translated confirmation or reinterpret command IDs. | +| BEX-CENTER-13 — Onboarding, updates and release notes | Welcome and About routes: Explain value, selected profile, permissions and changes with resumable nonsecret onboarding and verified update links. | personal-settings; available-on-local-center | An update never expands grants or changes a user's selected profile without review. | +| BEX-CENTER-14 — Privacy controls and reset center | Privacy and recovery routes: Pause all features, disconnect credentials, clear caches and reset selected settings with explicit scope. | personal-settings; available-on-local-center | A data reset preserves unrelated GitHub content and requires review before deleting authored local notes. | +### Integrated Copilot setup and management (18 capabilities) + +| ID / feature | Surface and observable result | Access / default | Boundary acceptance | +|---|---|---|---| +| BEX-SETUP-01 — Setup entry and repository confirmation | Local setup route: Confirm the exact repository and show inspect, configure, repair or full setup as separate journeys. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | A URL, local checkout and selected GitHub account mismatch blocks application. | +| BEX-SETUP-02 — Shared full questionnaire | Packaged setup wizard: Use the shared setup questionnaire, catalog and validation for every existing CLI/web choice. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Extension-only defaults cannot silently create a second setup policy. | +| BEX-SETUP-03 — Effective configuration inspector | Copilot configuration route: Inspect understood bindings, repository/organization precedence, source times and unknown values. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | A Secret name or complex workflow expression is not displayed as a verified effective value. | +| BEX-SETUP-04 — Focused runtime adjustments | Configuration quick adjustments: Review current/new value and existing scope, then delegate the existing narrow approved adjustment transaction. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Structural changes, scope movement and unknown bindings require the full reviewed setup journey. | +| BEX-SETUP-05 — Runner and verification setup | Setup runtime stage: Plan supported runner profiles, required runtime versions and verification setup with ownership preserved. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Generated starter files do not count as a working verification environment. | +| BEX-SETUP-06 — Credential role guidance | Protected credential handoff: Explain operator, bot and provider credential roles and open the paired trusted local setup step. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | No setup/bot/provider secret enters content scripts, extension messages or extension storage. | +| BEX-SETUP-07 — Permission audit progress | Setup permission stage: Show canonical metadata-only initial read and approved final write-probe progress from the shared engine. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | A write probe is a real temporary mutation and cleanup uncertainty remains a partial result. | +| BEX-SETUP-08 — Reviewed installation plan | Setup review stage: Show exact files/resources, scope, defaults, conflicts, changed facts and consequences before privileged approval. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | A changed plan or target invalidates prior approval and requires a new review. | +| BEX-SETUP-09 — Presets and organization reuse | Setup planning stage: Select named reviewed presets and organization inheritance with per-repository differences displayed. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | A preset cannot carry credentials, grant permissions or overwrite unrelated workflow customization. | +| BEX-SETUP-10 — Batch repository setup | Batch selection and review: Preview an explicit bounded repository set and exact per-item plans using the shared batch engine. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | One approval cannot silently include a newly discovered repository or changed per-item plan. | +| BEX-SETUP-11 — Protected application and progress | Paired local setup authority: Run Apply only through the CLI-owned current review/controller and stream redacted effects back to the center. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | The extension cannot invoke arbitrary shell commands, push managed refs or bypass final grant re-audit. | +| BEX-SETUP-12 — Doctor and installation evidence | Setup result and health route: Separate file/resource application, metadata diagnosis, runner verification and live Action execution evidence. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Installed Secret presence does not prove credential validity or deployment success. | +| BEX-SETUP-13 — Drift, upgrade and maintenance plans | Configuration maintenance route: Compare the installed known manifest and current reviewed plan with safe preserve/replace decisions. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Unknown consumer files and newer schemas are never deleted or downgraded automatically. | +| BEX-SETUP-14 — Cancellation and partial recovery | Active setup and recovery route: Cancel before new effects, retain completed effects and expose exact cleanup/retry ownership. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Cancellation cannot undo completed writes or suppress an unresolved cleanup journal. | +| BEX-SETUP-15 — Offline intent preparation and handoff | Local wizard without companion: Prepare a nonsecret portable setup intent and import it into a later reviewed local setup session. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | An exported intent is never an approval or a trusted installation manifest. | +| BEX-SETUP-16 — CLI pairing and controller lifecycle | Connect local companion: Pair an explicitly launched local CLI session, bind repository/controller and show liveness/expiry. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | The extension never scans loopback ports or adopts a session from a page-supplied URL. | +| BEX-SETUP-17 — Plan revision and audit history | Setup review and result: Navigate redacted plan revisions and verified effects without reusing an old approval. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | A restored browser tab cannot regain controller authority after expiry or takeover. | +| BEX-SETUP-18 — Shared setup parity and documentation | Help and acceptance surfaces: Use the same setting catalog, localized explanations, examples and acceptance fixtures across CLI, web and extension. | cli-owned-setup; local-planning-available; pairing-and-apply-explicit | Any transport-specific unsupported step is explicit and cannot be silently skipped to claim completion. | + +Every capability uses: available -> preparing/loading -> ready or partial/unavailable -> explicitly acting where applicable -> verified complete/failed/unknown -> recover/dispose. Navigation, account changes and revoked access retire the active generation. Unknown effects never become retryable writes automatically. Private evidence remains session-scoped; user-authored persistent notes require a separate explicit choice. + +## 7. User-facing configuration + +| Mode/profile | Default | Authority and data | Required behavior | +|---|---|---|---| +| Page-local | Available on eligible supported pages | Current DOM/URL, no API credential | Native coexistence; explicit gestures for copy/navigation | +| Personal settings | Explicit user choice for stateful features | Versioned nonsecret local settings | Atomic import/migration/reset and visible inheritance | +| Selected-repository read | Off until Connect | User-owned least-privilege read session | Exact source identity/freshness/completeness and revocation | +| Bounded alert monitoring | Off; five explicit tracked targets | Optional alarms/notifications grants and shared read budget | Revalidate on wake; dedupe, quiet hours, pause/revoke and unknown evidence rules | +| Native human submission/handoff | Explicit per request | Verified context and native editor | Preserve drafts or native selection/input, preview scope and let the human submit/confirm | +| Explicit user write | Off until its separate grant is enabled | Exact selected-repository write profile | Intent preview, live recheck, single-use approval and read-back | +| CLI-owned setup | Explicit local pairing | Existing shared coordinator and protected authority page | No credential/Apply authority in page scripts or extension transport | + +Per-feature values are enabled/disabled, default profile, favorites and bounded presentation choices. Scope precedence is emergency pause > tab pause > repository > organization > host/account > global > packaged default; show each inherited source. Enablement does not grant host, GitHub, CLI or Action authority. Profile changes preview their full delta. Unknown feature/schema values are preserved inert for migration, never executed. The center companion defines names, bounds, persistence, export and examples. + +Notifications use the native notifications page and explicit native controls: the official REST notification API currently requires classic PATs. The product does not silently widen its fine-grained credential model to satisfy that endpoint. Context menus and attention monitoring request supported narrow optional browser permissions only from a user gesture. Chrome/Firefox offer basic OS notifications; Safari omits that unsupported permission and uses toolbar/local-center attention items with the same monitoring limits. Denial leaves the requested mode off until the user explicitly chooses an available channel. The product never requests browser history permission for its own local recents. + +General CI details have a separate supported source contract in integration §11.2: selected Checks read for check runs/annotations and Commit statuses read for status contexts. The Copilot projection remains authoritative for its own assessment and does not invent arbitrary annotations. Loaded native evidence is a labeled subset; denied/missing grants leave the dependent detail unavailable. Requiredness is unknown without current native or policy-bound requirement evidence. All canonical reads share the existing identity, pagination, byte, freshness and request budgets; this is required functionality with tested explicit grant/denial flows, not an omitted capability. + +## 8. Clean Architecture design + +Registry metadata and pure eligibility/availability/operation policies -> immutable feature use cases -> semantic DOM/read/draft/write/settings/setup ports -> browser/GitHub/CLI adapters. Presentation consumes credential-free view models. Concrete command selection, permission checks and mutation admission never live in a component or page selector. + +The shared setup package contains presentation and browser-safe contracts; the CLI retains provider/credential/filesystem authority. Structured dependency checks prohibit DOM/provider DTOs in domain/application and Node imports in extension bundles. Build checks compare catalog IDs, defaults, docs and case inventory with every registered feature module; missing or extra registrations block acceptance. A narrow MutationPort accepts a closed operation union, never arbitrary URLs/methods/bodies. Browser adapters are original, independently disposable and exercised against actual target artifacts. + +## 9. UI/UX and content contract + +One consistent information hierarchy applies to every surface: current state, completed facts, next transition, actor/action, impact/source links and expandable technical detail. The local center offers global feature search, permission explanations, command discovery, meaningful empty states and one primary action per view. Feature presets make a large catalog understandable; progressive disclosure exposes detail without withholding controls. + +```text +Copilot extension · My work Account: chosen identity +GitHub improvements ready · 12 repositories explicitly selected +3 review requests · 1 setup plan awaiting review · 2 unavailable sources +[Open review queue] [Review setup plan] [Inspect unavailable sources] +Features: search by problem, page, permission or keyboard command +``` + +Pending: “Loading selected sources; completed repositories remain available.” Action required: “Review the exact setup plan in the paired local authority page.” Blocked: “This operation needs Pull requests write; no request was submitted.” Partial: “Two selected issues updated; one denied; one outcome awaiting verification.” Complete: “Selected change read back on the displayed target.” Offline: “Local features and saved nonsecret preferences are available; connected facts are unavailable.” Each includes a source or recovery link and preserves existing work. + +Keyboard-only, visible focus, screen-reader names/live regions, reduced motion, light/dark/high contrast and 200% zoom at 320 CSS px are mandatory. English, Spanish, French and Portuguese have complete atomic catalogs. Native/OS shortcuts win. No hover-only essential control, nested fixed-height scroll trap, disruptive focus steal, unannounced filtering or full private content in diagnostics. + +## 10. Failure, recovery, and cleanup + +Unsupported page/DOM disables one feature; missing source/API/grant explains the limitation; stale/partial data stays labeled; navigation cancels reads; revoked identity invalidates caches; ambiguous mutation returns unknown outcome until canonical reconciliation. Bulk selection is explicit (maximum 20 items per reviewed operation) with independent receipts. Stop prevents new items, not already accepted effects. Never automatically roll back unknown provider state. Feature disable removes only owned DOM/listeners/observers; disconnect clears credentials/private cache and pauses operations. Authored notes/settings have separate explicit cleanup scope. + +## 11. Security, permissions, and privacy + +All page/comment/Markdown/message/URL input is untrusted. Source provenance and Action authority remain separate from a user's write credential. No server Secret value is read; no bot credential becomes a browser credential. Private scopes, selected repositories and current account are visible. Local center routes never expose credentials through deep-link parameters; browser/pairing capabilities remain background or CLI-owned and cannot cross content-script messages. Protected setup credential steps remain in the trusted same-origin local web page. A settings import cannot enable grants, execute a command or approve a plan. No telemetry or remote feature-code service is introduced. + +## 12. Observability and operational UX + +Per-feature health records include stable ID, enabled/available state, closed reason, target generation, last successful operation time and redacted correlation. Distinguish intent prepared, user approval, provider acknowledgement and observed result. Bounded local diagnostics are opt-in exports and omit private titles/source text, commands containing user prose, credentials and full browsing history. Keep at most 200 redacted entries/7 days; private operation details are session-only. Normal operation sends no external analytics. + +## 13. Compatibility, migration, rollout, and rollback + +All three browser targets are required. Package manifests/IDs, API floors, permissions, storage/background adapters and store evidence follow the platform companion. The full catalog remains visible with accurate availability; compatibility is never inferred from common source alone. A new feature added to the required catalog updates its docs, test inventory, permission/availability mapping and release checklist together. Supported settings migrate atomically; unknown future records remain inert/exportable. Staged channels validate one reviewed immutable artifact set and never advertise complete product acceptance while required features/evidence are missing. + +## 14. Testing strategy and numeric budget + +The feature inventory defines **659 distinct future feature cases**. Counts follow behavior and risk: local=3, personal settings=4, reads=4, drafts=5, explicit writes=7, setup=7, opted-in alert monitoring=7; each row contains its concrete normal and boundary scenario, then the relevant coexistence, state, permission, approval, replay and recovery cases. These are a minimum inventory, not permission to replace distinct behavior with repeated boilerplate tests. Equivalent scenarios must be merged and replaced with missing distinct coverage rather than counted twice. + +| Area | Minimum distinct cases | Behaviors/risks covered | +|---|---:|---| +| Navigation and context | 39 | 12 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Code, files and diffs | 47 | 14 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Pull requests and reviews | 55 | 14 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Issues, discussions and collaboration | 55 | 12 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Search and personal views | 29 | 8 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Notifications and attention | 32 | 8 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Actions, checks and delivery evidence | 47 | 10 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Releases, tags and repository changes | 31 | 8 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Personal workspaces and platform ergonomics | 30 | 8 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Copilot Action integration | 112 | 24 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Local configuration and product experience | 56 | 14 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Integrated Copilot setup and management | 126 | 18 concrete capabilities; normal, boundary and applicable policy/race/recovery cases. | +| Total feature cases | 659 | Explicit unique IDs/scenarios in the JSON inventory. | + +The primary retains **96 distinct core cases**; the control-center/setup companion adds **48 distinct cross-boundary cases**. Complete product minimum: **803 distinct automated cases**, without counting browser/version/locale matrix reruns as extra cases. The semantic specification validator recomputes the feature count, unique case IDs, family totals and traceability; summary numbers cannot override the actual inventory. + +Root thresholds remain. New pure eligibility/evidence/authorization/plan policies require 100% branch coverage; other new modules at least 95% statements and 90% branches, with all changed executable lines covered. Deterministic clocks/fakes plus semantic golden output cover duplicates, cancellation, out-of-order responses and partial effects. Actual extension-loaded Chrome/Firefox/Safari tests exercise every eligible registered capability; critical user journeys also run in the supported OS/version matrix. Real Safari, keyboard/screen-reader and human UX evidence is mandatory. No future case here is represented as already executed. + +## 15. Documentation and discoverability + +Every feature entry has a stable lowercase feature-ID documentation anchor and maps to user feature guidance, permission/availability explanation, configuration and troubleshooting. Add complete user journeys, all settings/defaults/examples, privacy/retention/export, shortcut reference, operation confirmation/recovery, Action compatibility/command contexts, setup prerequisites/credential roles/batch/recovery, contributor architecture/testing and release/migration/rollback. Register routes in docs.json, validate links/examples and expose contextual help from the actual feature state. Human docs and JSON catalog must agree; no “coming soon” row satisfies a required function. + +The specification package creates this SDD, the control-center/setup companion, the catalog JSON/schema and a semantic validator; the three original SDDs and catalog metadata are updated. Runtime files, platform manifests, docs pages and provider adapters are implementation deliverables described by the companions, not fabricated current evidence. + +## 16. Acceptance scenarios + +1. A clean installation provides useful page-local improvements and the complete local center without connecting a repository or starting a CLI. +2. A user finds any catalog function by problem/page, sees its default/grants, enables it explicitly and reverses it without harming native GitHub. +3. A reviewer resumes exact-revision work, filters visible content, navigates findings and prepares a native request without losing a draft. +4. A maintainer sees honest complete/partial/stale sources and can perform a reviewed permitted operation with an inspectable result. +5. A setup operator completes the shared configuration journey with identical policy/plan/audit semantics across CLI, local web and extension presentation. +6. Permission denial, incompatible producer, expired CLI, worker suspension and changed head never produce false success or unsolicited effects. +7. Every registered function has actual target-browser, accessibility, locale, documentation and behavioral evidence before full product acceptance. + +## 17. Requirements traceability + +| Requirement | Capabilities | Explicit feature tests | Companion/docs ownership | +|---|---|---|---| +| CAT-NAV | BEX-NAV-01, BEX-NAV-02, BEX-NAV-03, BEX-NAV-04, BEX-NAV-05, BEX-NAV-06, BEX-NAV-07, BEX-NAV-08, BEX-NAV-09, BEX-NAV-10, BEX-NAV-11, BEX-NAV-12 | 39 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-CODE | BEX-CODE-01, BEX-CODE-02, BEX-CODE-03, BEX-CODE-04, BEX-CODE-05, BEX-CODE-06, BEX-CODE-07, BEX-CODE-08, BEX-CODE-09, BEX-CODE-10, BEX-CODE-11, BEX-CODE-12, BEX-CODE-13, BEX-CODE-14 | 47 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-REVIEW | BEX-REVIEW-01, BEX-REVIEW-02, BEX-REVIEW-03, BEX-REVIEW-04, BEX-REVIEW-05, BEX-REVIEW-06, BEX-REVIEW-07, BEX-REVIEW-08, BEX-REVIEW-09, BEX-REVIEW-10, BEX-REVIEW-11, BEX-REVIEW-12, BEX-REVIEW-13, BEX-REVIEW-14 | 55 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-ISSUE | BEX-ISSUE-01, BEX-ISSUE-02, BEX-ISSUE-03, BEX-ISSUE-04, BEX-ISSUE-05, BEX-ISSUE-06, BEX-ISSUE-07, BEX-ISSUE-08, BEX-ISSUE-09, BEX-ISSUE-10, BEX-ISSUE-11, BEX-ISSUE-12 | 55 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-SEARCH | BEX-SEARCH-01, BEX-SEARCH-02, BEX-SEARCH-03, BEX-SEARCH-04, BEX-SEARCH-05, BEX-SEARCH-06, BEX-SEARCH-07, BEX-SEARCH-08 | 29 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-NOTIFY | BEX-NOTIFY-01, BEX-NOTIFY-02, BEX-NOTIFY-03, BEX-NOTIFY-04, BEX-NOTIFY-05, BEX-NOTIFY-06, BEX-NOTIFY-07, BEX-NOTIFY-08 | 32 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-CI | BEX-CI-01, BEX-CI-02, BEX-CI-03, BEX-CI-04, BEX-CI-05, BEX-CI-06, BEX-CI-07, BEX-CI-08, BEX-CI-09, BEX-CI-10 | 47 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-RELEASE | BEX-RELEASE-01, BEX-RELEASE-02, BEX-RELEASE-03, BEX-RELEASE-04, BEX-RELEASE-05, BEX-RELEASE-06, BEX-RELEASE-07, BEX-RELEASE-08 | 31 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-WORK | BEX-WORK-01, BEX-WORK-02, BEX-WORK-03, BEX-WORK-04, BEX-WORK-05, BEX-WORK-06, BEX-WORK-07, BEX-WORK-08 | 30 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-COPILOT | BEX-COPILOT-01, BEX-COPILOT-02, BEX-COPILOT-03, BEX-COPILOT-04, BEX-COPILOT-05, BEX-COPILOT-06, BEX-COPILOT-07, BEX-COPILOT-08, BEX-COPILOT-09, BEX-COPILOT-10, BEX-COPILOT-11, BEX-COPILOT-12, BEX-COPILOT-13, BEX-COPILOT-14, BEX-COPILOT-15, BEX-COPILOT-16, BEX-COPILOT-17, BEX-COPILOT-18, BEX-COPILOT-19, BEX-COPILOT-20, BEX-COPILOT-21, BEX-COPILOT-22, BEX-COPILOT-23, BEX-COPILOT-24 | 112 explicit cases in the JSON test inventory | product/integration/platform companions; feature, permission and recovery docs | +| CAT-CENTER | BEX-CENTER-01, BEX-CENTER-02, BEX-CENTER-03, BEX-CENTER-04, BEX-CENTER-05, BEX-CENTER-06, BEX-CENTER-07, BEX-CENTER-08, BEX-CENTER-09, BEX-CENTER-10, BEX-CENTER-11, BEX-CENTER-12, BEX-CENTER-13, BEX-CENTER-14 | 56 explicit cases in the JSON test inventory | control center and setup companion; feature, permission and recovery docs | +| CAT-SETUP | BEX-SETUP-01, BEX-SETUP-02, BEX-SETUP-03, BEX-SETUP-04, BEX-SETUP-05, BEX-SETUP-06, BEX-SETUP-07, BEX-SETUP-08, BEX-SETUP-09, BEX-SETUP-10, BEX-SETUP-11, BEX-SETUP-12, BEX-SETUP-13, BEX-SETUP-14, BEX-SETUP-15, BEX-SETUP-16, BEX-SETUP-17, BEX-SETUP-18 | 126 explicit cases in the JSON test inventory | control center and setup companion; feature, permission and recovery docs | + +The JSON feature entry is the exact requirement -> feature/use case -> case IDs -> documentation mapping. The primary BEX-P requirements, integration I requirements and platform D requirements remain cross-cutting constraints; the center companion owns its HUB requirements and 48 integration cases. No family is satisfied by a diagram or test-count statement alone. + +## 18. Implementation sequence + +1. Freeze this complete catalog, schemas, case ownership, UX prototypes and executable architecture/quality constraints. +2. Build the local application, shared setup presentation, portable feature registry and three real-browser harnesses. +3. Implement native GitHub families in dependency-sized reviewed increments with docs and acceptance evidence together. +4. Implement read/evidence producers and all compatible Action request/context tools; preserve server authorization. +5. Implement reviewed optional writes and paired setup metadata/controller transport with threat/race/partial-state acceptance. +6. Complete every remaining family, documentation, accessibility/locales, performance, signed artifacts and real target-matrix evidence. +7. Audit the complete catalog/case inventory and release receipts; missing required rows prevent general acceptance. + +These are work waves, not alternative product scopes or reduced release tiers. + +## 19. Definition of Done + +- [ ] All 150 catalog functions are implemented with documented defaults and honest availability states. +- [ ] All 803 distinct cases, coverage, dependency/schema/permission checks and actual browser matrix pass. +- [ ] Local center and shared setup have policy/plan/permission/cleanup parity and no duplicated authority. +- [ ] All UI states, four locales, keyboard/screen-reader/theme/narrow/zoom/reduced-motion review pass. +- [ ] Performance/memory/request/notification budgets and pause/disposal behavior pass on representative workloads. +- [ ] User, operator, setup, permission, recovery, architecture, test and release docs/examples/navigation are complete. +- [ ] Every partial effect and failure has source-linked recovery and bounded safe replay behavior. +- [ ] Signed artifact identities, provenance, store/support/privacy and rollback evidence are reviewed. +- [ ] Catalog evidence distinguishes specification, implemented tests and live browser/provider proof. +- [ ] No required capability or material architecture/security/public-contract decision is deferred behind a completion claim. + +## 20. References and decisions + +- [GitHub command contract](../docs/issues/comment-commands.mdx) and existing setup/local-web SDDs define current repository authority. +- [Browser options pages](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Options_pages) and [Chrome options](https://developer.chrome.com/docs/extensions/develop/ui/options-page) support packaged extension configuration UI. +- [GitHub workflow runs](https://docs.github.com/en/rest/actions/workflow-runs), [workflows](https://docs.github.com/en/rest/actions/workflows) and [issue comments](https://docs.github.com/en/rest/issues/comments) define separate read/mutation resources. +- [GitHub notifications](https://docs.github.com/en/rest/activity/notifications) documents classic-token-only endpoints; native notification interaction is the chosen complete supported experience. + +Primary sources inspected 2026-10-25; reverify provider/API/store details at implementation and release. All behavior, architecture, selectors, assets and text are independently authored. The product documentation contains no external extension branding or copied functional descriptions. diff --git a/specs/github-browser-extension-platforms-and-delivery.md b/specs/github-browser-extension-platforms-and-delivery.md new file mode 100644 index 000000000..651b04034 --- /dev/null +++ b/specs/github-browser-extension-platforms-and-delivery.md @@ -0,0 +1,672 @@ +# GitHub Browser Extension — Platforms, Architecture and Delivery + +- Status: Ready for review — proposed, not implemented or browser-verified +- Date: 2026-10-25 +- Catalog capability ID: `github-browser-extension` +- Last verified: 2026-10-25, primary documentation and source research only +- Owners: Copilot maintainers; release owner provisions each store account/signing identity before distribution +- Scope: Shared extension architecture, Chrome/Firefox/Safari adapters, lifecycle, privacy, performance, testing and distribution. +- Related issues/PRs: [#694](https://github.com/vypdev/copilot/issues/694) +- Required review gates: product UX, architecture, testing, documentation, security/operations +- Open decisions blocking design readiness: None. Actual device evidence, registered package identities and store accounts are release prerequisites, not assumed available. + +## 1. Executive summary + +One portable TypeScript core delivers [the product](github-browser-extension.md) +and [Action contract](github-browser-extension-action-integration.md). Narrow +adapters handle browser APIs and GitHub's changing page structure. Each feature +owns its nodes/listeners/observers, mounts once and can be disabled independently. +Desktop Safari participates from the first working shell through release. + +```text +Shared pure policies/contracts → use cases → browser/GitHub/DOM adapters + → generated target manifest → actual extension-loaded tests + → Chrome package / signed Firefox package / Safari containing app +``` + +No browser sidebar API, persistent background process, remote code patch or +resident CLI/web server is a runtime prerequisite. + +## 2. Problem, current behavior, and evidence + +There is currently an Action/CLI and a local web setup assistant, with existing +domain/application/adapter boundaries. There is no catalogued browser runtime, +browser manifest or verified extension package. Root `pnpm-workspace.yaml` +currently supplies dependency overrides; it is not evidence of a multi-package +extension build. `package.json` and the current architecture/coverage validators +must remain supported as a new package is introduced in follow-up work. + +Primary sources establish differing background environments, storage access and +Safari distribution, rather than one universal manifest. Technical mechanics +research found useful feature isolation/navigation/settings patterns (§20). +They inform original requirements; no implementation, selectors, text or assets +are copied. All platform/runtime statements here are proposed contracts until +the explicit evidence matrix passes. Retrospective classification is not +applicable to this prospective capability. + +## 3. Actors, surfaces, and terminology + +| Actor | Responsibility | Surface | +|---|---|---| +| Browser user | Site access, feature settings, optional session connection | Options/toolbar and github.com | +| Feature owner | Own DOM/listener lifecycle and tests | Feature module and scoped diagnostics | +| Platform maintainer | Browser-specific manifests/adapters and compatibility | Build, fixture and real browser matrix | +| Action maintainer | Integration producer and existing policy | Owning Action contracts | +| Release maintainer | Reproducible bundles, signing, store submission, rollback | CI artifacts and stores/TestFlight | + +`background` means an event-driven extension context, not necessarily a service +worker. `page generation` identifies one route/object identity. `owned DOM` means +nodes created by the extension, not GitHub's editors/content. `session` survives +background suspension where the API supports it, and ends on browser restart. +`WebKit test` is not proof that a Safari extension package loaded and operated. + +## 4. Goals, non-goals, and fixed invariants + +- **D1 — Browser parity:** U1–U6/K1–K3 have the same product meaning across the + required Chrome/Firefox/Safari desktop matrix and explicit minimums. +- **D2 — Architecture:** portable pure decisions, semantic ports, provider/DOM + adapters and composition have executable import/package boundaries. +- **D3 — Lifecycle:** scoped, idempotent mount/refresh/dispose, bounded observers, + canceled work and native coexistence prevent duplicate/broken page controls. +- **D4 — Privacy/security:** least permissions, validated messages/URLs, + session-only secrets/private evidence and account/isolation cleanup. +- **D5 — Inclusive UI:** original controls follow GitHub themes, keyboard/focus, + assistive technology, locale and narrow-layout contracts. +- **D6 — Operations/performance:** measurable page/bundle/memory/request budgets, + sanitized local diagnostics and per-feature recovery. +- **D7 — Settings/migration:** bounded original settings, atomic migrations, + previous-version recovery and no token/private-data export. +- **D8 — Proof:** the shared numeric test budget, real extension-loaded matrix, + fixtures and human artifacts are release gates. +- **D9 — Packaging/distribution:** reproducible target outputs, independent + versioning, review/signing prerequisites and honest rollback. +- **D10 — Documentation/rollout:** planned versus delivered behavior, install and + recovery guidance, catalogue evidence and staged three-browser availability. + +Normative tables below refine these IDs. Non-goals: iOS/iPadOS/Android, +Enterprise hosts, webRequest interception, cookie access, host-wide automation, +custom code/CSS, native messaging, browser history access, AI runtime and hosted +telemetry. A per-feature hotfix can only arrive as a reviewed packaged release; +The complete product contains no remote executable or remote CSS injection service. + +## 5. Current versus proposed product journey + +| Stage | Current evidence | Proposed delivery | +|---|---|---| +| Build | One Action/CLI package and web setup | Separate extension package plus narrow shared contract entrypoint | +| Mount | No extension | One registry-driven page generation with feature disposal | +| Suspend | No browser contract | Persist nonsecret settings, keep protected session state, revalidate on resume | +| Test | Existing Action tests/validators | Add fixture, package, real browser and human gates | +| Distribute | Existing Action/npm delivery | Independent browser packages/store lifecycles | +| Recover | Existing Action recovery | Per-feature pause plus reviewed extension/settings rollback | + +```mermaid +flowchart LR + S[Shared source and locked dependencies] --> B[Browser build adapters] + B --> C[Chrome MV3] + B --> F[Firefox MV3 event page] + B --> A[Safari MV3 event page] + C --> T[Actual extension-loaded evidence] + F --> T + A --> T + T --> R[Review, signing and staged distribution] +``` + +Text equivalent: shared source and lockfile produce three target packages; +each is loaded as a real extension and tested before signing/store distribution. +Failure of one required target blocks advertising the complete three-browser product. + +## 6. Functional behavior and platform state + +### 6.1 Browser and OS compatibility matrix (D1) + +These are **chosen compatibility floors**, not claims that those are today's +latest versions or that they have already been tested. Record exact browser/OS +builds in each release receipt and increase floors through a documented release +decision if current APIs or provider support require it. + +| Concern | Chrome | Firefox | Safari | +|---|---|---|---| +| Product API floor | 140 | 140, including ESR 140 compatibility | 18.2 | +| Supported desktop OS baseline | Windows 11, macOS 15.2+, Ubuntu 24.04 LTS | Windows 11, macOS 15.2+, Ubuntu 24.04 LTS | macOS 15.2+ | +| Release test versions | Chosen floor in isolated fixtures; current and previous stable | Floor/ESR 140 fixtures; current stable and currently supported ESR ≥140 | 18.2 isolated fixtures; current and preceding supported Safari major ≥18.2 | +| Manifest | Generated MV3, `background.service_worker`, module | Generated MV3, nonpersistent `background.scripts`; no service-worker assumption | Generated MV3, nonpersistent `background.scripts`; containing app | +| Background durability | Can terminate; use asynchronous session/settings ports | Event page may unload; same revalidation contract | Event page may suspend; same revalidation contract | +| Storage | local nonsecret settings; protected session data | Same; default session not exposed to content scripts; no `setAccessLevel` assumption | Same; explicit site/session permission handling | +| UI | In-page panel/options/toolbar | Same | Same; no vendor-only side panel prerequisite | +| Testing package | Unpacked artifact and store candidate | Temporary load then signed beta candidate | Actual containing-app extension enabled in Safari; TestFlight candidate | +| Distribution | Chrome Web Store ZIP | AMO listed signed XPI | App Store Connect/TestFlight/App Store containing macOS app | + +Minimum manifests declare the exact floors. Version detection is a compatibility +notice; APIs are also feature-detected. Unsupported APIs disable only dependent +features and identify why. Every deviation in a release matrix is disclosed; +maintainers cannot count a generic WebKit run as Safari evidence. Real user +acceptance uses currently vendor-supported builds; old floor fixtures contain +no real credentials or personal repositories. The release support table +distinguishes API compatibility from currently supported vendor/OS versions. + +Mobile/Enterprise: separate unsupported host/platform products for this declared desktop github.com contract, no matching script registration on extra +hosts. Responsive page layout still works in desktop narrow windows. Future +Enterprise support requires per-origin opt-in, credential/config cache isolation, +API compatibility and exact host registration. Future mobile work needs its own +input/navigation/background/store matrix; it is not implied by shared source. + +### 6.2 Manifest/API matrix and defaults + +| Capability | Manifest / adapter decision | Degradation | +|---|---|---| +| GitHub page scripts | Static isolated content script for `https://github.com/*`, top frame only, packaged JS/CSS | Missing site access: explain how to enable; no request on arbitrary sites | +| API connection | Optional host permission `https://api.github.com/*`, requested by explicit Connect gesture | Standalone remains fully usable | +| Settings/session | Required `storage`; use known keys/get(null), not newer `getKeys` APIs absent at floors | Quota/storage error disables persistence/connection explicitly | +| Clipboard | User-gesture DOM clipboard adapter; no blanket read permission | Copyable selected text and native copy fallback | +| Toolbar/options | Packaged options page, toolbar opens settings/current feature status | No resident popup connection required | +| Background scheduling | No persistent timer/keepalive; normal page reads use activity/nextAllowedAt; explicit alert monitor uses one optional bounded alarm | Hidden pages do not poll; only the independently opted-in monitor follows I6 alarm limits | +| Context menus and optional alerts | Narrow optional contextMenus/alarms grants from an explicit gesture; notifications only in Chrome/Firefox target manifests | Safari uses toolbar/center attention items; no unsupported permission or browser history permission | +| Programmatic injection | Not required for static github.com matching | No `scripting`/`activeTab` permission without a later reviewed need | + +Browser/extension message listeners register synchronously at background entry, +before async initialization, to survive wakeup. Target manifests are generated +from a typed base plus allowlisted differences, never string replacement over +one vendor's JSON. Firefox add-on ID and Safari bundle/container identities are +maintainer-owned release metadata. Development IDs are distinct from published +identities and cannot share real credentials. + +The attention workflow is required on every target, with an explicit channel +matrix: Chrome/Firefox support basic OS notifications plus the local center; +Safari uses a toolbar badge and the same accessible center attention list. +Safari does not expose the WebExtensions notifications API, so its generated +manifest omits that permission and its UI never offers an OS channel or asks +for an unsupported grant. Do not introduce Web Push, a hosted relay or native +messaging to emulate it. The bounded alarm monitor and its privacy, quiet-hour, +deduplication and revocation rules apply to both adapters. On Chrome/Firefox, +denial of OS notification permission offers an explicit switch to the local +channel; it never silently enables a different channel or removes an existing +attention item. Tests cover unsupported/denied channels as well as delivery; +no system-notification or exact-delivery claim is made for Safari. + +### 6.3 Feature lifecycle (D3) + +```text +Observe route identity → decide eligibility/settings → mount once + → scoped native content refresh → update owned view + → route/identity/pause change → abort requests → disconnect observers/listeners + → remove owned nodes → restore native focus/state → next generation +``` + +| State | Transition | Required behavior | +|---|---|---| +| Ineligible/disabled | Route, unsupported API, setting or protected path | No DOM work or network for that feature | +| Mounting | Eligible and unique pageGeneration | Create controller and scoped ownership; check anchor before write | +| Mounted | Successful DOM insertion | Stable accessible controls; no duplicate native equivalent | +| Refreshing | Relevant scoped mutation/soft navigation | Reconcile keyed owned nodes; preserve native editors/focus | +| Unsupported/error | Anchor missing or feature exception | Stop only affected feature, show local reason in diagnostics | +| Disposing | Navigation, pause, revoke, extension generation change | Abort, remove listeners/observers/owned nodes; no native subtree deletion | +| Disposed | Resources released | Late work checks epoch and becomes no-op | + +Route detection uses current canonical URL and observed repository/object ID; +GitHub Turbo/React soft-navigation events may be hints but are not exclusive +truth. Validate route/anchors after history restoration, partial refresh and +visibility/pageshow. Registry observes a scoped route root and relevant anchors, +not every subtree in the document. Each request captures immutable page/settings/ +credential epochs. A moved virtualized node is reconciled, not treated as a new +permission/operation. Native editor subtrees are never reparented or rewritten. + +## 7. User-facing configuration + +Product §7 is the complete personal schema; integration §7 is the repository +manifest. This companion adds no experimental feature flags or unbounded custom +code inputs. D7 requires atomically validated migrations and one previous +nonsecret settings version, explicit import/reset previews and namespace cleanup +on feature retirement. Maximum settings JSON is 64 KiB, 100 repo overrides and +20 saved views/repo. A future schema is preserved read-only, not destructively +normalized; a higher compatible package or explicit reset is the recovery. + +Recommended: shipped defaults, session connection only when needed, no optional +host until Connect. Alternative: a repository-specific compact view and paused +connected functions during troubleshooting. Trust/host/byte limits, no auto-write, +protected session exposure and typed message methods are non-configurable. + +## 8. Clean Architecture design (D2) + +### 8.1 Physical boundaries and toolchain + +Proposed placement, to be introduced by later implementation PRs: + +```text +extension/ + package.json private workspace package; independent version + src/domain/ eligibility, settings, IDs, pure view policies + src/application/ use cases and semantic ports + src/adapters/{github,browser,dom}/ + src/infrastructure/ entrypoints, composition, target manifests + src/presentation/ immutable view models, original components/CSS + test/{fixtures,contracts,integration}/ +src/domain/browser_extension_contract/ + index.ts only shared import entrypoint + schema.json versioned closed wire schema + ... pure parser/semantic validation +``` + +The root Action imports its pure domain contract normally. The extension may +import only that explicit shared barrel from root `src/`; no Action runtime, +Node utility, provider DTO or deep implementation import. Do not move existing +Action policies wholesale into browser bundles. Shared types/parser belong to +the domain; existing authoritative decisions remain Action-owned. + +Add `extension` to pnpm's workspace package selection while preserving existing +overrides and root package behavior. Use the repository's locked Node/pnpm +toolchain, TypeScript, a locked Vite build plus explicit target manifest +generation, and Vitest for extension-specific pure/DOM tests. Use Playwright +where it can actually load the Chrome artifact; Firefox and Safari acceptance +may require browser-native/manual harnesses and signed candidates. Tool/library +versions are selected and locked in the implementation PR, verified against +official documentation then; this SDD does not prescribe unverified future APIs. +Root commands orchestrate contract build/typecheck, extension targets/tests and +existing Action verification without requiring browser packages in the published +Action runtime. Existing root coverage thresholds are not replaced by an easier +extension-only aggregate. + +### 8.2 Semantic responsibility and trust graph + +| Layer | Owns | Must not import/receive | +|---|---|---| +| Pure domain | Feature eligibility, bounded settings, IDs, state/next action | Browser globals, DOM, Node, GitHub SDK, tokens | +| Application | MountFeature, ReadContext, ReadFindings, PrepareDraft, Pause, MigrateSettings | Concrete HTTP/DOM/storage/provider DTOs | +| Ports | Immutable semantic input/result unions and cancellation/epoch | Arbitrary URL/command/body capability | +| Adapters | GET mapping, browser API differences, scoped GitHub anchors/editor | Product authorization/readiness policy duplication | +| Infrastructure | Target manifest generation, synchronous listeners, composition | Business decisions hidden in entrypoints | +| Presentation | Accessible original renderer/CSS and immutable VM | Token, mutating GitHub client, raw remote HTML | + +```mermaid +flowchart LR + CE[Isolated content entry] --> APP[Application use cases] + APP --> DOM[Semantic DOM port] + DA[Scoped GitHub DOM adapter] --> DOM + APP --> BG[Typed background messages] + BE[Background entry and sender validation] --> READ[ReadContext use case] + READ --> PURE[Pure shared contract and evidence policies] + READ --> GP[GitHub read port] + GA[Allowlisted GET adapter] --> GP + READ --> SP[Protected session port] + SA[Browser storage adapter] --> SP + APP --> VM[View model and renderer] +``` + +Text equivalent: isolated page entry calls use cases through DOM and typed +background ports; background validates the sender, reads GitHub/session state +and pure contracts, then returns a credential-free view to the renderer. + +The graph above illustrates the read/evidence path. Closed optional write use cases use a different semantic mutation port behind current intent/actor/revision policy; setup uses the separate shared coordinator/authority graph in the center companion. Neither adds network or credential authority to presentation. + +### 8.3 Executable architecture constraints + +Implementation introduces structured checks for: +1. Import graph: pure contract/domain has no side effects/Node/browser imports; + application imports ports/domain only; presentation has no credential/network + or mutation dependencies; root cross-imports use the single shared barrel. +2. Bundle scan/manifest parse: no Node builtins, `eval`, remote executable script, + unapproved web-accessible assets, wildcard hosts or new permission drift. +3. Typed message schema: known methods only, closed bounded payloads, valid + sender/tab/frame/origin and page/credential epochs; no arbitrary fetch gateway. +4. GitHub adapter: separate GET-only read and closed named-write endpoint allowlists, live intent checks and cross-origin credential stripping; + tests fail if an extension mutating method or command submission is added. +5. Schema/golden compatibility: valid/invalid snapshots/config/migrations and + original DOM fixtures; public contract changes require explicit version rules. +6. Package/target receipts: lockfile and generated manifests/build hashes match the + source revision; reproducibility check builds twice in clean temporary output. + +### 8.4 Full local application and shared setup packages + +The [complete catalog](github-browser-extension-functional-catalog.md) and [local center/setup SDD](github-browser-extension-control-center-and-setup.md) add required application routes and private shared setup-presentation/setup-contracts packages. Existing Svelte 5/TypeScript/Vite presentation is extracted through browser-safe explicit barrels; CLI/server/provider/crypto modules remain outside the browser dependency graph. Root commands build both local-web and extension consumers and enforce shared question/locale/plan fixture parity. Do not import the current Node web bridge/server into options code or create a second questionnaire/installer. + +The options page is a complete packaged application in its own tab, registered through options_ui/open_in_tab or a verified target equivalent. Toolbar, native page Settings entry and browser manager reach it. Every target has real options-page navigation, storage/messaging, accessibility and protected setup-handoff evidence. No remote iframe/SPA is loaded. Optional context-menu/alert grants are explicit; recents use only extension-owned navigation and never browser history permission. Local setup adds only an opt-in exact 127.0.0.1 broker host grant; no loopback scanning, broad CORS or generic content-script proxy. If exact-origin broker verification is unavailable, the tested trusted local-web handoff provides the complete setup journey. + +All new pure evidence/eligibility/intent/approval policies require 100% branches; other new modules require 95% statements/90% branches and covered changed executable lines, while root thresholds remain. Each module stays at most 220 lines and Svelte component at most 90 unless a named reviewed exception and equivalent decomposition evidence exists. Feature modules load on eligibility; the registry must not eagerly mount or scan for all 150 features. + +## 9. UI/UX and content contract (D5) + +Use product §9 state variants. All injected controls are original markup/styles +using bounded tokenized styles; a shadow-root panel isolates its presentation +where compatible with focus/accessibility, while inline helpers use namespaced +owned nodes. Shadow DOM is styling isolation, not a credential/security boundary. +Theme adapter maps GitHub light/dark/high-contrast tokens without replacing global +CSS or adding generic selectors that restyle native components. + +```text +Extension settings +GitHub improvements: Enabled Repository: vypdev/copilot +Connected context: Not connected (optional) +[Connect read access for this session] + +Feature status +Diff navigation: Enabled +Conversation controls: Unavailable on this page — anchor not found +[Pause conversation controls] [Open native page] + +Privacy +View settings stay in this browser. Connection ends when the browser restarts. +No browsing-history or code telemetry. [Review permissions] [Disconnect] +``` + +Focus, live announcements, shortcut/help behavior, EN/ES/FR/PT fallback and narrow +layout are product P7. Extension update/feature failures use nonmodal inline +notices; do not interrupt native typing, open surprise welcome tabs per update, +or request more permission as error recovery. Setup onboarding appears once +after install or explicit Open setup and shows standalone value first. + +## 10. Failure, recovery, and cleanup + +| Failure / partial result | User effect and retained state | Recovery | Cleanup owner | +|---|---|---|---| +| One feature exception | Other features/native GitHub remain; diagnostic names affected feature | Toggle it off or update reviewed package | Feature controller releases owned nodes/listeners | +| Background suspension | Pending read canceled/unknown, settings retained | Wake → revalidate account/page/source before rendering | Scheduler/session port | +| Session store absent/lost | Connected mode unavailable/disconnected | Explicit reconnect; no local-storage credential fallback | Credential epoch reset | +| Storage quota/migration failure | Previous nonsecret settings retained | Export/reset/retry once; never partial overwrite | Atomic settings store | +| Optional API site access revoked | Context unavailable, U features remain | User regrants exact optional origin | Abort and clear credentials/private evidence | +| Base GitHub site access revoked | No enhancement runs | Explain in toolbar; native page unaffected | Dispose feature generation | +| Extension update on open tab | Old generation disposed; no duplicate controls | One reload/resume affordance | Generation handshake | +| Browser close/disable/uninstall | No repository side effects | Intentional reconnect on reinstall/restart | Session API clears data; settings local removed by uninstall | + +Disconnect atomically advances credential epoch *before* aborting requests and +deleting session token/evidence/cache; late responses cannot repopulate it. +Account switch uses the same path. Browser logout is not reliably observable by +an extension: pause when a visible logged-out/different-viewer signal is observed +and require explicit reconnect. Never claim that a PAT is invalidated by GitHub +web logout. Optional token itself is revoked only through GitHub native settings. +At most five explicit named session identities, partitioned by host/user/role, with one selected identity per operation; no silent cross-account continuation. Optional write-role credentials never broaden the read role or setup authority. + +## 11. Security, permissions, and privacy (D4) + +Secrets/private evidence use `storage.session` in the background with default +content-script exposure disabled; call trusted-context access control where the +target supports it. Firefox lacks `setAccessLevel`, so no cross-browser policy +may assume the method exists. The API's default restricted session exposure is +required and tested. If a target cannot enforce this boundary, C features remain +unavailable; it is a release blocker for connected parity, not a disk fallback. +Do not keep credentials solely in service-worker globals or persistent local/ +sync/IndexedDB storage. Session loss is a clear disconnect, not guessed success. + +Options receives the user-entered token and sends it only through an +extension-origin credential-setting message; content scripts cannot call that +method. Background returns no token to any caller. Session caches for private +data share the credential epoch and are never exported. Browser extension +session storage is not advertised as an encrypted hardware-backed secret store. + +Every content message validates extension sender ID, top-level frame, exact +HTTPS github.com origin, current tab route/object/epoch and closed method schema. +Credential/settings commands require packaged extension-origin sender paths. +Reject externally_connectable messages and web-page `postMessage` command bridges; +The product needs neither main-world injection nor page-cookie access. A compromised +page cannot ask the background to fetch arbitrary URLs, switch repository, +retrieve a secret or execute code. Redirected API reads cannot send Authorization +to another origin. Remote strings are bounded text; URLs/commands/DOM selectors +are never assembled from free-form page content. + +Do not register/inject on login, signup, password/session, OAuth authorization, +personal account/token settings or repository administration routes. Exact route +predicates and native fixtures test both direct load and soft navigation into +these paths. Content registration alone may match github.com, but entrypoint +exits before observers, storage reads containing private data or background +requests on a protected route. No all-frames/related-frame injection. + +Incognito/private browsing is a declared unsupported environment: explicitly disable in manifests +where possible and check context/sender flags before every connected read/write +to personal settings. If users manually allow it, refuse connection and retain +no private browsing evidence. No `history`, `cookies`, `webRequest`, +`nativeMessaging`, blanket host or unlimited-storage permission. +The sole attention-monitor permission path is the optional `alarms` grant and, +on Chrome/Firefox for the selected OS channel, optional `notifications` in +§6.2. Request grants only after the user explicitly enables the bounded I6 +monitor and selects its targets/channel. Denial leaves that requested mode +off; revocation stops that mode and its queued delivery until an explicit new +choice. Neither permission is an install-time requirement or authority for +unrelated background activity. Safari's local channel needs no notifications +grant. +No third-party remote font/code/telemetry fetch; assets are packaged. Any added +permission is a separately reviewed contract change with visible upgrade impact. + +## 12. Observability, performance and operational UX (D6) + +### 12.1 Performance budgets + +These are release targets, not current measurements. Reference fixture: desktop +viewport 1440×900, four logical CPU cores/8 GiB RAM class machine, fixed original +HTML with 10,000 native nodes, 100 diff files and 100 conversation threads; +network facts are replayed with deterministic latency. Run 30 warm measurements +after five warmups per target; retain fixture/tool/device/browser IDs. Report +median/p95 and baseline separately so native GitHub/network time is not attributed +to extension work. + +| Area | Required bound | Measurement | +|---|---|---| +| Packaged content code | ≤500 KiB gzip JS across required content entrypoints; ≤50 KiB gzip CSS | Build receipt with compressed byte counts | +| Initial feature work | p95 ≤100 ms attributable JS in first second; no extension task >50 ms | Browser profiler on fixed fixture | +| Scoped refresh | Process ≤200 changed nodes/batch and yield after ≤8 ms target; hard task cap 50 ms | Deterministic mutation fixture + profiler | +| Observers | ≤1 route observer plus ≤1 scoped observer per mounted feature; none after dispose | Instrumented lifecycle counters | +| Owned DOM | ≤500 initial nodes; ≤50 findings mounted at once, virtualized/paged to 100 snapshot cap | Semantic DOM assertions | +| Retained growth | After 20 issue/PR/route cycles, ≤2 MiB growth over first settled extension state; added retained heap target ≤20 MiB/tab | Five profiler comparisons/target with GC/procedure disclosed | +| Idle | No ordinary foreground-independent polls, keepalive or protected-page observers; only the explicit bounded I6 monitor may wake | Fake clocks and real suspension inspection | +| API | I6 concurrency/byte/hour/rate-limit budgets | Scheduler traces with no live waits | + +Heap measurement uses the supported profiler for each engine, not an assumed +universal browser API; receipts document measurement limitations. Failure to +establish a comparable measurement is recorded as missing evidence, not a pass. +Large native pages/virtualized lists beyond fixtures keep bounded work and show +partial loaded scope; do not remove caps to make data appear complete. + +### 12.2 Complete-product UX and application quality gates + +The center's packaged initial application code must be at most 2 MiB gzip JS, with lazy feature/detail modules; its meaningful first interaction is p95 at most 1 second on the declared reference machine after package load, and a local search/profile response is p95 at most 100 ms. A source read may take network time: show progress within 200 ms and retain completed independent sources. Measure on at least 30 cold and 30 warm runs per target. Registry metadata cannot eagerly activate all 150 modules. Existing content-script, task/heap/DOM/request limits above remain in force. + +Extension-owned UI and complete journeys require [WCAG 2.2 AA](https://www.w3.org/TR/WCAG22/), automated accessibility checks with zero critical/serious violations, and real keyboard/NVDA/VoiceOver evidence. Human review covers all primary states in light/dark/high contrast, reduced motion, 320 CSS px/200% zoom and English/Spanish/French/Portuguese. No essential hover-only action, focus trap or fixed-height nested scroll pane is allowed. + +Run 12 representative end-to-end tasks with at least six participants covering developer/reviewer/maintainer and first-time setup roles (72 task attempts). Require at least 95% unassisted completion, no critical authority/target misunderstanding, no draft loss or accidental write, and no unresolved critical/high-severity usability defect. Measure whether users find a named feature within 30 seconds and identify the current blocker/responsible actor within 10 seconds. Record consented anonymized outcomes, concrete failures and resulting fixes; test count alone cannot satisfy this gate. Daily actions should start within three interactions from their applicable surface; a deliberate confirmation is retained for consequential effects. + +Documentation acceptance covers every registered function, setting/default/grant, availability state, command context, setup/credential/plan/cleanup journey and upgrade/rollback. Validate example fixtures and route/link/assets, provide context help in the actual UI, and have a reader outside the implementation team complete normal setup and one failure/recovery exercise from the docs alone. API/store facts are reverified at release; incomplete human/browser/store evidence remains pending. + +### 12.3 Local diagnostics + +The content adapter retains at most 100 sanitized events/session. The separately opted-in local-center diagnostic history is capped at 200 redacted entries/7 days; these are distinct bounded stores. Aggregate counters include: +feature ID, adapter/browser version, error code, page type (no full URL), request +outcome/cached flag and disposal counts. No token, query text, draft, path, +comment, user identity or private repo name by default. Manual export previews +the exact ≤64 KiB nonsecret report and supports clearing it. There is no remote +diagnostic submission or automatic issue creation. Existing Action summaries +remain native source links, not copied bulk logs. + +## 13. Compatibility, migration, rollout, and rollback + +D7: schema-1 settings are bounded and local; migration validates into a fresh +record then commits atomically, retaining one previous settings version. Future +schema is read-only/exportable; never erase an unknown record. Retired feature +IDs have an explicit rename/remove map, a migration fixture and a release note. +Do not retire a user override merely because a module failed to load once. + +Native coexistence: before mounting, detect a semantic native equivalent and +disable only the redundant helper. If another extension provides the same +control, favor native usability and a clear feature-disable path; do not mutate +that extension's nodes. Broken-feature recovery is local settings/pause or a +reviewed packaged update, with no remote JavaScript or CSS hotfix channel. + +Rollout gates are D8/D9: all-target shell → internal fixture/pilot → beta store/ +TestFlight → stable release. Safari packaging begins with the shell, not after +Chrome's feature completion. A store-specific incident may pause that rollout, +but complete three-browser acceptance remains blocked until parity evidence exists. +Rollback restores an approved compatible code/settings pair. If stores reject a +lower version, submit a higher numeric build containing the reviewed revert. +Disable connected manifest support independently while preserving standalone +features and native Action publications. No user token is included in backups. + +## 14. Testing strategy and numeric budget (D8) + +The complete product budget is **803 distinct cases**: 96 retained core, 659 feature cases and 48 local-center/setup cross-boundary cases. This companion owns F/N lifecycle, S security and E packaging areas within the core and cross-cuts the new feature/center inventories; it does not add a duplicate 96. Every requirement maps to its explicit case IDs. +Maintain root Action thresholds and separate extension reports; pure trust and +authorization policies require 100% branch coverage. Test decisions, not getters +or mirrored implementation. Use deterministic clocks, aborts, fake providers, +original HTML fixtures and semantic assertions in addition to snapshots. + +### 14.1 Real execution matrix + +| Target | Automated minimum | Actual extension evidence | Human minimum | +|---|---|---|---| +| Chrome | Pure/DOM/manifest suites; extension-loaded smoke where runner supports it | All 150 eligible registered functions and public/private/permission-denied fixtures, suspension, back/forward | Keyboard and NVDA on Windows; light/dark/200% | +| Firefox stable + chosen ESR | Same core suites and target manifest; browser-native loaded harness or recorded manual smoke | Real signed/temporary extension, event-page restart, private read denial | Keyboard and NVDA on Windows; theme/focus | +| Safari | Same pure/DOM/schema suites; WebKit may supplement layout only | Actual enabled containing-app extension on macOS, permission prompts, session/suspension, TestFlight beta | VoiceOver, keyboard, light/dark/200% and narrow layout | + +Additionally run Chrome/Firefox smoke on the OS baselines in §6.1, recording +exact oldest/current-version coverage and gaps. A mocked `browser.*` object +proves policy mapping only. Signed/store candidates require install/enable/update +checks separate from unpacked load. Organization-restricted access needs a +controlled acceptance record when available; denied/unknown behavior is always +tested deterministically and unavailable live access is disclosed honestly. + +Each receipt records source commit, lockfile hash, package hashes, browser/OS, +extension ID/install method, fixture identity, steps and assertions, pass/fail, +time, screenshots/profiler traces and limitations. Use a controlled private +test repository and separate read token; never capture tokens or real private +code/drafts. At least one original screenshot per main state/target and human +reader result is retained outside generated intermediates and linked in the PR. +An evidence index distinguishes local automation, actual browser, human UX and +store acceptance. Missing categories stay pending, not checked off by proxy. + +### 14.2 Contract/packaging test inventory + +bex-E-C01/bex-E-C02/bex-E-C03 validate foundational package loading; the catalog/center cases validate all 150 functions and complete workflows on every target. Each package preserves protected +routes. bex-E-C04/bex-E-C05 prove background restart with protected session state or honest +disconnect. bex-E-C06 revokes optional origin while reads are pending. bex-E-C07/bex-E-C08 exercise +no producer and mixed schema versions. bex-E-C09/bex-E-C10 prove nonsecret migration and +uninstall cleanup. bex-E-C11 covers native/other-extension coexistence; bex-E-C12 covers the +measurable budgets. bex-N-C01–bex-N-C14 instrument resource counts after each lifecycle edge. +bex-S-C01–bex-S-C16 attempt malformed/sender/URL/secret/command/export/account attacks under +the closed ports. These are future tests, not claims of executed evidence. + +## 15. Documentation and discoverability (D10) + +Product §15 is the documentation inventory. Platform delivery adds exact +Chrome/Firefox/Safari install/enable/revoke/update/uninstall instructions, support +floors/current vendor support table, keyboard/screen-reader behavior, Safari +containing-app/TestFlight workflow, signing prerequisites and version rollback. +Architecture docs include physical/import/message graphs, typed port catalog, +original fixture guidance and reproducibility receipts. Permission/privacy docs +explain session expiry, PAT native revocation, no incognito support and no +telemetry. Navigation is registered only for existing pages with correct +availability labels; check docs routes/frontmatter/assets/examples and README +links using repository validators. Maintain translations with complete fallback. + +## 16. Acceptance scenarios + +1. Load each exact target package at its declared compatibility floor in fixtures: + standalone U features operate without token/Action/API permission. +2. Connect on supported live browser: optional exact API host is requested by user + gesture, read session works and C features match product/integration semantics. +3. Suspend/restart background: retain safe session timing/credential state or + visibly disconnect; never restore stale view from global memory alone. +4. Soft navigation, React refresh, virtualized insert/remove and back/forward: + one owned generation, no native editor loss and zero leaked observers. +5. Spoofed sender/foreign repo/unsafe URL/arbitrary fetch: no provider request, + credential disclosure or page/remote code execution. +6. Logout signal/revocation/disconnect/account switch mid-read: invalidate epoch + before clear; late response cannot repopulate private state. +7. Private browsing enabled manually: refuse connected operation and do not + persist private navigation evidence/settings. +8. Settings import invalid/future schema/quota failure: retain current settings + and show explicit recovery; no secret/private data appears in export. +9. A native equivalent appears or one feature breaks: only that feature retires/ + pauses; native GitHub and remaining features work. +10. Keyboard/screen-reader, themes/zoom/narrow and EN/ES/FR/PT pass with real human + evidence; screenshots alone are not an accessibility result. +11. Reproducible packages, performance bounds, browser evidence and store/signing + prerequisites pass before stable availability claims. +12. Reviewed rollback/new higher build restores behavior/settings without + overwriting native content, Action state or human drafts. + +## 17. Requirements traceability + +| Requirement | Owning boundary | Test/evidence | Documentation | +|---|---|---|---| +| D1 | Browser target manifests/adapters | bex-E-C01–bex-E-C03, §14 real matrix | compatibility/installation | +| D2 | Domain/application/ports/composition/build | bex-F-C01–bex-F-C12, bex-S-C16, structured import/package checks | architecture | +| D3 | Registry/controllers/DOM adapters | bex-N-C01–bex-N-C14, bex-A-C05, bex-E-C04–bex-E-C05/bex-E-C11 | features/troubleshooting | +| D4 | Sender parser/credential/session/GET ports | bex-S-C01–bex-S-C16, bex-E-C06/bex-E-C10, real private-read denial | permissions/privacy | +| D5 | View/focus/theme/locale adapters | bex-V-C01–bex-V-C14 and §14 human artifacts | features/compatibility | +| D6 | Scheduler/observer/diagnostic budget policies | bex-E-C12, bex-N-C14, bex-A-C07–bex-A-C12, profiler receipts | troubleshooting/privacy | +| D7 | Atomic settings store/migrations | bex-F-C03–bex-F-C12, bex-E-C09 | configuration/upgrade | +| D8 | Test orchestration/evidence receipt | 96 inventory, three-target receipt review | architecture/contributor guide | +| D9 | Target build/sign/store pipeline | bex-E-C01–bex-E-C03/bex-E-C08–bex-E-C10, reproducibility/sign receipts | installation/compatibility | +| D10 | Release availability/docs/navigation | Documentation validators and review gates | All planned product pages | + +## 18. Implementation and release sequence (D9) + +1. Introduce shared barrel, private extension workspace, target manifests and + structured boundary checks. Preserve root overrides/build/package contents. +2. Load the minimal shell in all three browsers and register stable development + IDs/fixture receipt format. Select/lock library versions with primary docs. +3. Implement features/settings/lifecycle and protected connection, with original + fixtures and companion Action producer work; update docs per slice. +4. Complete 96 cases, coverage, actual-browser/human/performance proof and + reviewed package reproducibility/SBOM/license inventory. +5. Maintainer provisions Chrome Web Store and AMO publisher accounts and Apple + Developer/App Store Connect access, exact IDs, privacy/support/store assets + and signing custody. These are named role prerequisites; not completed by + writing a specification or by generating a ZIP. Signing credentials stay in + the reviewed release environment, never the extension/Action user bundle. +6. Produce independent Chrome ZIP, Firefox signed XPI and Safari extension ZIP/ + containing-app candidate from the same reviewed commit. Safari default is + App Store Connect's Web Extension Packager and TestFlight; Xcode conversion + is the supported development/fallback route when packaging capability requires + it. Actual Mac/Safari testing remains necessary even if packaging uses the web. +7. Beta/pilot on each target, review privacy/permission prompts and updates, then + explicitly authorized store submission/stable release. No store action or + enrollment is authorized by this specification issue. + +Extension semantic version is independent of Action/CLI. Use a deterministic +monotonic numeric package version `major.minor.patch.build` with each component +0…65535 and at least one nonzero; keep a release manifest mapping it to the +human semantic version/channel and Safari bundle build. Beta → stable builds +increase the numeric build, rather than trying to downgrade a prerelease package. +Stable extension IDs/app bundles are reserved by the release owner before beta; +the exact values are release metadata, not unbounded user settings. + +## 19. Definition of Done + +Specification delivery: platform choices, architecture, permission/storage +boundaries, test/evidence budgets, delivery owners and documentation are concrete +and consistent; proposed status/capability and validators remain honest. + +Future implementation gates: +- [ ] D1–D10 and product/integration requirements have traceable acceptance. +- [ ] Three real target packages load; minimum/current/ESR/platform matrix is recorded. +- [ ] Structured dependency/message/schema/manifest/package constraints pass. +- [ ] 803-case complete-product floor, root/changed-module coverage and pure-policy branches pass. +- [ ] Real accessibility/theme/narrow/locale and profiler evidence meet budgets. +- [ ] Session secrets, private cache, pause/revoke/cleanup and migration pass. +- [ ] Original implementation/fixtures/assets and dependency/license inventory are reviewed. +- [ ] User/setup/operator/contributor docs and navigation are complete/validated. +- [ ] Store identities/accounts/signing/privacy/support and rollback are ready. +- [ ] Catalog/generated artifacts distinguish design, implementation and live proof. +- [ ] Specification/doc/build checks pass; no material design decision remains open. + +## 20. Primary sources, technical provenance and decisions + +Sources accessed 2026-10-25; reverify changing API/store details at implementation +and release. These support platform facts, not a claim of execution. + +- [Chrome content scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts): isolated script environment and page interaction. +- [Chrome service-worker lifecycle](https://developer.chrome.com/docs/extensions/develop/concepts/service-workers/lifecycle): background termination and restart design. +- [Chrome storage](https://developer.chrome.com/docs/extensions/reference/api/storage): separate local/session/sync uses and trusted-context controls. +- [Mozilla cross-browser guidance](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension) and [background manifest](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background): differing runtime/manifest behavior. +- [Mozilla session storage](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/session) and [primary compatibility data](https://github.com/mdn/browser-compat-data/blob/main/webextensions/api/storage.json): session support at chosen floors; `getKeys` and `setAccessLevel` are not portable assumptions. +- [Apple compatibility](https://developer.apple.com/documentation/safariservices/assessing-your-safari-web-extension-s-browser-compatibility): target-specific API assessment. +- [Apple web packaging](https://developer.apple.com/documentation/safariservices/packaging-and-distributing-safari-web-extensions-with-app-store-connect) and [distribution](https://developer.apple.com/documentation/safariservices/distributing-your-safari-web-extension): Packager, TestFlight, containing-app/signing prerequisites. +- [Chrome remote-code policy](https://developer.chrome.com/docs/extensions/develop/migrate/remote-hosted-code): packaged executable code and reviewed update route. +- [Mozilla extension signing](https://extensionworkshop.com/documentation/publish/signing-and-distribution-overview/): signed distribution options. + +### Original design and technical decisions + +The product is independently designed and implemented. Feature mechanics inform ordinary requirements such as isolated activation, cancellation/disposal, settings migration, narrow permissions and native coexistence; no external extension source, selectors, CSS, assets, test corpus, prose or branding is incorporated or named in product documentation. + +Chosen: full 150-function catalog, 803-case minimum, complete packaged options application, shared original Svelte setup UI/contracts, CLI-owned privileged setup with a separate nonsecret broker and trusted authority handoff, three target manifests, portable typed ports, protected session identities, optional closed write operations, original feature registry, no resident hosted service/remote executable patches, and actual Safari evidence. Rejected: a Chrome-only release advertised as three-browser complete, iframe of the protected local setup, global DOM scanning, worker keepalive, broad all-site grants, generic HTTP/shell mutation proxy, and generic WebKit as Safari-extension proof. + +Alarm adapters follow [Mozilla alarms](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/alarms) and [Chrome alarms](https://developer.chrome.com/docs/extensions/reference/api/alarms), inspected 2026-10-25. Do not assume Chrome 150 persistAcrossSessions support at the Chrome 140 floor or on other engines; recreate only the user-enabled logical alarm after validating safe session state. + +The [Mozilla notifications API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications) and its [browser compatibility data](https://github.com/mdn/browser-compat-data/blob/main/webextensions/api/notifications.json), inspected 2026-10-25, document no Safari notifications support. The target channel matrix above is normative; browser packaging and acceptance must verify it against the shipped versions. diff --git a/specs/github-browser-extension.md b/specs/github-browser-extension.md new file mode 100644 index 000000000..29a983348 --- /dev/null +++ b/specs/github-browser-extension.md @@ -0,0 +1,701 @@ +# GitHub Browser Extension — Complete Product and Quality Contract + +- Status: Ready for review — proposed, not implemented +- Date: 2026-10-25 +- Catalog capability ID: `github-browser-extension` +- Last verified: 2026-10-25, repository/source research only; no extension execution +- Owners: Copilot maintainers (product, engineering, security and release) +- Scope: Complete GitHub productivity product: 150 required capabilities, local control center, full Copilot integration and shared setup across desktop Chrome, Firefox and Safari. +- Related issues/PRs: [Issue #694](https://github.com/vypdev/copilot/issues/694) +- Required review gates: product UX, architecture, testing, documentation, security/operations +- Open decisions blocking design readiness: None for the declared desktop github.com product. Implementation, real browser/security/accessibility evidence and store acceptance remain mandatory delivery gates. + +## 1. Executive summary + +The extension is a complete GitHub productivity application: 150 required capabilities in 12 families, a packaged full-page configuration/work center, comprehensive Copilot Action tooling and an integrated shared setup journey. Page-local improvements and local configuration work without the Action, credentials or a resident server. Connected evidence, native command drafts and separately enabled reviewed operations add repository context without transferring policy ownership to the browser. + +The [complete functional catalog](github-browser-extension-functional-catalog.md) defines every required function, its access/default, observable result, boundary and tests. The [local center and setup contract](github-browser-extension-control-center-and-setup.md) defines configuration UX and reuse of existing setup UI/application decisions. Work is implemented in dependency-sized increments; all registered functions and quality gates remain required for product acceptance. + +```text +Install → enable selected GitHub improvements → visit issue/PR + → optionally connect repository → inspect current context/findings + → prepare supported request → review and submit in GitHub → inspect Action result +``` + +The user owns personal settings and comment submission. GitHub owns native facts. +The Action owns automation policy, evidence and managed branch lifecycle. This +document defines product behavior; [integration](github-browser-extension-action-integration.md) +defines its data contract and [platforms](github-browser-extension-platforms-and-delivery.md) +defines browser architecture, security and delivery. The complete catalog and center/setup companions are equally normative; no smaller umbrella inventory limits their scope. + +## 2. Problem, current behavior, and evidence + +### 2.1 Problem + +Developers repeatedly navigate files, references and conversation history. Authors +and reviewers also reconstruct Copilot progress from labels, status comments, +findings, checks and runs. Shared automation cannot retain each person's view +preferences or add contextual controls throughout their browser session. + +### 2.2 Observed behavior + +1. `README.md` describes the existing issue → branch → implementation → PR → review + → release flow, CLI and local web setup assistant. +2. `specs/catalog.json` catalogues managed issue lifecycle, SDD readiness, comment + authorization, Bugbot reconciliation and exact-revision PR readiness. +3. `src/application/usecases/read_copilot_status_workflow.ts` combines native + issue/PR facts, SDD evidence and PR readiness; it is not a browser API. +4. `src/application/ports/pull_request_status_read_ports.ts` already separates + read-only evidence access from approval mutation. +5. `specs/comment-automation-and-authorization.md` restricts command contexts and + write authority. A general issue comment cannot invent a branch target. + +These are integration evidence, not evidence that browser support exists. +The proposed catalog entry references existing Action entrypoints, read ports, +status tests and documentation because the catalog requires existing evidence +paths even for proposed capabilities. Those paths establish the integration +baseline only. This change verifies specifications, schemas and examples; it +does not establish extension code, runtime tests or browser support. +The current local web setup assistant configures repositories; it is not the +extension runtime or a required resident server. + +### 2.3 Evidence and unknowns + +Related owning contracts: [managed lifecycle](managed-issue-and-branch-lifecycle.md), +[SDD status](pre-branch-sdd-status-readiness.md), +[PR readiness](guarded-pull-request-approval-status.md), +[commands](comment-automation-and-authorization.md), +[findings](bugbot-review-state-reconciliation.md), +[publication](semantic-github-publication-and-notification.md) and +[locale](repository-locale-and-localization.md). +Browser primary sources and technical mechanics research are recorded in the +platform companion. Prototype performance, real browser results and store +acceptance are unknown until implementation; this proposal claims none of them. + +### 2.4 Retrospective classification + +Not applicable: this is a prospective product contract, not an as-built baseline. + +## 3. Actors, surfaces, and terminology + +| Actor | Goal | Entry point | Visible surfaces | +|---|---|---|---| +| Developer | Navigate and read more efficiently | Repository/file/diff/list | Inline controls, personal preferences | +| Issue/PR author | Understand the next action | Issue or PR | Copilot panel and native composer | +| Reviewer | Inspect current findings with history | PR conversation or Files changed | Findings navigator and native review threads | +| Repository maintainer | Enable trusted connected data | Reviewed default-branch configuration | Discovery, compatibility and Action source links | +| Extension operator | Configure/recover a browser installation | Toolbar/options | Permissions, session connection, feature diagnostics | + +**Standalone** means page-local features without API credentials or Copilot. +**Connected** means explicitly enabled reads from a compatible repository. +**Current** means identity and freshness checks pass at observation time. +**Historical** is inspectable past evidence, never current readiness. +**Prepared** means a draft exists; **submitted** and **executed** are later facts. +The extension's name in examples is provisional `Copilot`; no store or trademark +availability is claimed. Naming does not block this design. + +## 4. Goals, non-goals, and fixed invariants + +### 4.1 Normative product requirements + +- **P1 — Independent utility:** U1–U6 work without a token, Action or backend. +- **P2 — Complete scope:** all 150 catalog capabilities, the complete local center and integrated setup are required on all three declared desktop browsers; implementation order cannot reduce final acceptance. +- **P3 — Honest context:** K1/K2 use the integration contract, show source/time and + distinguish missing, stale, partial and historical evidence from completion. +- **P4 — Explicit effects:** command drafts preserve native human submission; separately enabled regular triage/run operations use closed reviewed intents, fresh live checks and verified results. Rendering never authorizes an effect. +- **P5 — Personal control:** each feature has an explicit default, repository + override and reversible disable/pause/reset path. +- **P6 — Native usability:** filters expose hidden counts, never silently hide + required action, and leave native content, editors and checks reachable. +- **P7 — Inclusive presentation:** all primary states have keyboard, screen-reader, + light/dark, zoom/narrow and complete EN/ES/FR/PT presentations. +- **P8 — Bounded work:** page work, requests and notification noise obey the + platform/integration budgets and stop on pause, navigation or revocation. +- **P9 — Verifiable delivery:** the complete catalog, 803-case minimum (96 core + 659 feature + 48 center/setup integration cases), documentation and real browser/UX/security evidence accompany implementation. + +The formal requirement IDs BEX-P1 through BEX-P9 correspond to P1 through P9 +below. All normative tables below refine those requirements. A reference to a companion's requirement +incorporates that requirement; explanatory examples are not evidence of delivery. + +| Requirement | Behavior | +|---|---| +| BEX-P1 | Standalone utility without Action, credential or backend. | +| BEX-P2 | Complete 150-capability product, local center and shared setup across Chrome, Firefox and desktop Safari. | +| BEX-P3 | Source-bound, complete and honest current versus historical context. | +| BEX-P4 | Exact-context native drafts plus explicitly reviewed closed optional operations; no unsolicited effects. | +| BEX-P5 | Bounded personal defaults, overrides, migration, pause and recovery. | +| BEX-P6 | Idempotent native coexistence and explicit reversible filtering. | +| BEX-P7 | Accessible, localized and responsive presentation for every primary state. | +| BEX-P8 | Bounded DOM/network work and cancellation without unsolicited writes. | +| BEX-P9 | Traceable tests, secure artifacts, documentation and actual browser proof. | + +### 4.2 Outcomes and non-goals + +Acceptance demonstrates: standalone installation without authentication; one +primary next action in every connected state; one mount per feature/page; no +request caused by rendering that posts a comment or invokes AI; and the complete +browser matrix and catalog acceptance before a release is advertised as complete. + +This specification change defines future implementation and acceptance, not a runtime release. Required functions include comprehensive page tools, read-only context, native human-submitted commands, selected optional regular-label/assignee/run operations, full local configuration/workspaces and shared setup. The product never silently approves/merges/deploys, runs arbitrary scripts, scrapes cookies, changes managed refs or hidden Action state, or introduces hosted billing/telemetry. Mobile and Enterprise remain separately verified host/platform contracts and are not advertised implicitly. + +### 4.3 Fixed invariants + +P3/P4/P6 cannot be weakened by settings. An extension cannot grant Action write +authority, create or rename a managed branch, infer a missing PR association, or +turn absent findings into zero. Native controls remain the recovery path. + +## 5. Current versus proposed product journey + +| Stage | Current | Proposed | User effect | +|---|---|---|---| +| Install | Separate automation/setup tooling | Explain standalone and optional connection | Immediate value without credentials | +| Navigate | Native links and repeated manual browsing | U1/U2 helpers beside known destinations | Fewer context switches | +| Read | Repeated layout/filter choices | U3/U4, with visible filtering | Personal readable view | +| Understand work | Compare comments/checks/runs | K1 with verified links and observation time | Know status and responsible actor | +| Review | Open findings across threads | K2 grouped navigator with native links | Find active versus historical evidence | +| Request work | Remember command/context restrictions | K3 preview in the correct composer | Explicit target and human submission | +| Recover | Guess whether extension/Action failed | Per-feature reason and native fallback | Isolated recovery | + +```mermaid +flowchart LR + I[Install and grant GitHub page access] --> U[Standalone improvements] + U --> O[Opt in to repository connection] + O --> V[Validate configuration and current publication] + V --> C[Context and findings] + C --> D[Prepare supported native draft] + D --> H[Human reviews and submits] + H --> A[Action authorizes and executes] + A --> V +``` + +Text equivalent: install → standalone use → optional connection → verified +context → prepared draft → human submission → Action result → refreshed context. +Denied connection leaves standalone use available. + +## 6. Functional behavior and state model + +### 6.1 Complete product inventory + +The normative [functional catalog](github-browser-extension-functional-catalog.md) and its [structured inventory](browser-extension/feature-catalog.v1.json) define all 150 required functions, defaults, permissions, sources, freshness, privacy, browser support, acceptance and test IDs. U1–U6 and K1–K3 are umbrella names for foundational controls and the context/findings/draft entry points; the complete catalog defines final product scope. Test cases use the retained bex namespace; detailed feature cases use bexp and center/setup integration cases use bexhub. + +| Family | Required functions | User-visible scope | +|---|---:|---| +| Navigation/context | 12 | Command palette, exact links, ref/branch context, previews, bookmarks and menus | +| Code/files/diffs | 14 | Tree/path/symbol navigation, filters, readability, patch/history/rename context and review checkpoints | +| Pull requests/reviews | 14 | Readiness, findings/threads, drafts, changed-since-review, reviewers, conflicts/queue and evidence | +| Issues/discussions | 12 | Triage/forms/relationships, explicit adjustments, duplicate research, notes, bulk selection and dependencies | +| Search/views | 8 | Query builder, saved searches, bounded cross-repository results, collections and accessible navigation | +| Notifications/attention | 8 | Native inbox grouping/selection/actions, personal snooze, optional alerts and privacy | +| Actions/checks | 10 | Source-aware checks/attempts/annotations, failure comparisons, explicit retry/cancel, dispatch handoff and artifacts | +| Releases/repository changes | 8 | Tags/comparisons/unreleased evidence, changelog drafts, provenance/security navigation and attention | +| Personal workspaces | 8 | Selected my-work views, named workspaces, queues, profiles, session drafts and compatibility | +| Copilot Action | 24 | Full lifecycle, SDD workbench, current supported commands, findings, sync/doctor/history, release/deploy/recovery and policy | +| Local control center | 14 | Full application, feature/profile/connection/permission/appearance/language/privacy/activity/recovery management | +| Shared setup/management | 18 | Inspector, complete questionnaire, quick/batch plans, runners, credential handoff, audits, Apply, doctor/drift/recovery and parity | + +### 6.2 Feature/access model + +Local controls require only page access; additional selected-repository reads require explicit connection. Native drafts retain append/keep/cancel, correct context and human submission. Optional writes are separate named regular triage/run operations, never a generic request client; protected lifecycle/deployment operations hand off to authoritative native controls/Action. Setup uses shared presentation and the CLI-owned protected authority described in the center companion. Every function needs tested unavailable/partial/recovery behavior; access requirements do not remove a function from delivery acceptance. + +Features share native coexistence, original adapters/assets, disposal, source honesty, privacy, performance and accessibility requirements. No feature reads drafts for remote analysis or starts a model on page open. No personal preference is written into repository files. + +### 6.3 State model + +| State | Entered when | Visible meaning / primary action | Transition / owner | +|---|---|---|---| +| Standalone | Connected mode off/manifest absent | Improvements available / Configure connection | User can opt in; U features independent | +| Loading | Bounded collection in progress | Checking current context / no action needed | Reader → current, partial, unavailable | +| Pending | Verified Action work in progress | Waiting for run / Inspect run | Action completes or user revisits | +| Action required | Verified clarification/review blocker | Waiting for author/maintainer / Open source question | Human acts, Action republishes | +| Blocked | Proven failed prerequisite | Work blocked, retained facts shown / Inspect blocker | Operator/author repairs; fresh evidence | +| Partial | Some facts succeeded, others unavailable | Completed facts retained; no aggregate readiness / Inspect missing evidence | Fresh complete collection | +| Complete snapshot | All required facts pass at fenced identity | Latest assessment complete at time T / View result | New revision/event invalidates snapshot | +| Stale | TTL, identity, policy or generation changed | Previous result is historical / Refresh current context | Reader obtains fresh source | +| Unavailable/incompatible | Denied/malformed/future major/missing producer | Current context unavailable / Open native GitHub | Operator restores compatibility/access | +| Paused | Repository/features disabled | Extension paused here / Resume | User resumes; old requests stay canceled | + +Terminal native close/merge is shown directly with its reason and source; a +historical percentage or finding card cannot reopen it. State priority and +evidence ownership are specified in I4/I5. + +## 7. User-facing configuration + +Settings schema version 1 is extension-owned; no secrets are accepted by this +schema. Unknown top-level keys, unknown feature IDs, invalid enums or oversized +imports are rejected with no partial write. Import size is at most 64 KiB and +repository overrides at most 100. Repository identities use GitHub numeric ID, +not a mutable name alone; renamed repositories retain their preference mapping. + +| Input | Type / default | Allowed values | Scope and persistence | +|---|---|---|---| +| `features` | Map; defaults in §6.1 | Known IDs → boolean | Global plus per-repo override, local storage | +| `density` | Enum; `comfortable` | `comfortable`, `compact` | Global, repo override | +| `locale` | Enum; `auto` | `auto`, `en`, `es`, `fr`, `pt` | Global; browser primary language then complete-message EN fallback | +| `theme` | Enum; `github` | `github`, `light`, `dark` | Global; GitHub tokens/contrast respected | +| `shortcuts` | Boolean; `false` | true/false | Global, repo override; fixed conflict-aware binding catalog | +| `connected` | Boolean; `false` | true/false | Explicit numeric repository opt-in | +| `paused` | Boolean; `false` | true/false | Global or repository; pause wins over enabled flags | +| `savedViews` | Map; empty | ≤20 query strings, ≤2,000 chars each; issue/PR routes only | Repo; explicit restore, not automatic route replacement | + +K1/K2/K3 feature switches default enabled, but their eligibility is false until +the user explicitly connects that repository; they never auto-connect. U5 help +exists by default while additional key bindings stay off. If all connected features are +disabled, no connected reads are scheduled. Import cannot grant host permission, +restore a credential or activate a new repository connection: imported connection +preferences require a separate local user opt-in, and an active pause remains +effective until explicitly resumed. Export previews repository preference scope; +private API evidence and credentials are never part of settings. + +Precedence: fixed safety/compatibility rules → emergency pause → tab pause → repository pause → +repository setting → organization setting → host/account preference → global preference → shipped default. The center companion owns profile names and limits. Snapshots take an +immutable settings version per operation; a pause/revocation cancels it even +after snapshotting. Unknown newer schema makes settings read-only with export +and downgrade guidance; it is never silently rewritten. Migrations are atomic, +idempotent and retain one previous non-secret settings version until next +successful startup. Reset preview distinguishes global from current-repo reset; +disconnect also clears protected session data under D4. + +Recommended settings: comfortable, locale auto, GitHub theme, U features at their +row defaults, shortcuts and connected mode off. Alternative: compact and U5 +enabled in one repository, with K1/K2 connected there only. A repository cannot +override personal locale, grant credentials or turn K3 into auto-submission. + +## 8. Clean Architecture design + +The platform companion D2/D3 specifies the component graph, semantic ports and +executable import/message/manifest boundaries. Product owns feature eligibility, +information hierarchy and next-action selection; presentation never owns +authorization or provider state. Integration I1–I10 owns transport/provenance and +Action-side changes. Browser code cannot import the Action composition root, +Node process/filesystem adapters or runtime credentials. + +View settings are durable local state. API evidence and credentials are separate +session state. Native GitHub and Action publications remain the durable shared +source; browser memory never establishes a successful operation. + +## 9. UI/UX and content contract + +### 9.1 Primary context panel + +P3/P7: heading `Copilot`, one textual state, completed facts, next actor/action, +impact, source links, then collapsed technical detail. Do not show internal schema +IDs in the main flow. On wide screens mount beneath issue/PR header; at ≤760 CSS +pixels use an in-flow collapsible panel, not a fixed overlay. Native headings, +editors and checks are not displaced or hidden. No injected control duplicates a +native equivalent with the same destination and effect. + +```text +Copilot · PR #158 Updated 24 seconds ago +Changes required — waiting for the PR author +Completed: specification published · branch verified · CI completed +2 current findings; review covers this revision +Next: inspect the findings before preparing a correction request. +[View findings] [Issue #142] [Specification] [Inspect run] +Technical details ▸ head/base, policy, run attempt and source time +``` + +### 9.2 Required state variants + +```text +Pending +Copilot is reviewing this revision. Branch verification completed. +No action required. [Inspect current run] + +Action required +Specification needs your answer. Branch has not been published. +Next: the issue author answers Q2. [Open clarification] + +Blocked +Current context cannot confirm verification: the verification run failed. +The published specification and branch remain available. +Next: inspect the failure before retrying through GitHub. [Inspect blocker] + +Partial +Specification and branch verified. Current review evidence is unavailable. +No overall readiness is claimed. [Inspect available sources] + +Complete snapshot +Latest assessment completed for revision abc1234 at 10:42. +0 current findings with complete coverage. Human review still applies. +[View assessment] + +Stale +A newer revision is open. The 10:42 assessment describes the previous revision. +Current finding count is unknown. [Refresh current context] + +Unavailable / incompatible +Connected context is unavailable for this Action version. +Your GitHub view preferences still work. [Open native checks] +``` + +Errors follow impact → cause → action → retained facts. Sources use descriptive +links, and absent links are omitted rather than rendered as dead controls. +The findings view labels `Current`, `Historical`, `Coverage incomplete` in text; +color/severity icons supplement text. Empty current findings is shown only with +complete current coverage; otherwise `Current finding count unavailable`. + +### 9.3 Draft preparation and noise + +Preview target repository/PR/thread, exact command and consequence before editing. +For a nonempty editor, offer `Append request`, `Keep my draft`, `Cancel`; a +separate `Replace draft…` path previews the old draft and requires confirmation. +If safe targeting fails, show a copyable command and exact destination link. +Appending is idempotent by operation ID and current editor digest; no duplicate +append after rerender. Do not claim a copied draft was inserted. + +Opening/refreshing a page creates zero comments, notifications, Actions or AI +requests. K3 native submission creates the user's normal GitHub comment; existing +Action publication budgets remain authoritative. Extension diagnostics use local +nonmodal messages; no notification permission is requested. + +### 9.4 Accessibility and localization + +The complete product must meet WCAG 2.2 AA for extension-owned UI and complete user journeys; this is an acceptance target, not a claim about native GitHub. All four locales and the human evaluation gates in the platform companion are required. + +P7/D5: every action has an accessible name, visible focus and keyboard path; +expanded state is programmatic; dynamic results use a polite bounded status +announcement. Preserve focus on equivalent owned control after refresh, otherwise +restore a safe parent without stealing focus from native editing. Help bindings +are discoverable and conflict-checked. Respect reduced motion and 200% zoom, +320 CSS pixel layout, high contrast, and EN/ES/FR/PT complete catalogs. Resolve the +extension's locale once per render; unsupported language uses complete English. +Action publications retain their repository locale and are clearly attributed; +do not machine-translate command operands or diagnostic source text. + +## 10. Failure, recovery, and cleanup + +| Failure | Impact and retained facts | Recovery | Cleanup | +|---|---|---|---| +| Missing DOM anchor | A named feature unavailable; native page works | Disable feature or reload after update | Owned nodes/listeners only | +| Navigation while loading | Old response cannot affect new repo/PR | New page generation starts fresh | Abort old request/observers | +| Offline/denied/rate limited | Connected evidence unavailable/stale | Native source and bounded retry I6 | Purge denied private data | +| Bad settings import | Existing preferences retained | Correct error/export current version | No partial migration | +| Extension updated in open tab | Duplicate generation rejected | One refresh prompt; native UI stays | Retire old owned generation | +| Draft already edited | Request not inserted | Keep, append, replace explicitly, or copy | No draft telemetry/persistence | +| Pause/uninstall | Owned enhancement removed; repository unaffected | Resume/reinstall intentionally | D4 session/credential cleanup | + +The platform companion defines suspension, partial writes, settings quota and +rollback; the integration companion defines replay, stale identity and API +limits. No recovery automatically submits or retries a mutation. + +## 11. Security, permissions, and privacy + +P1/P4/P6 incorporate I7–I9 and D4. Standalone operation uses GitHub page access and +local settings. Optional API permission/authentication is requested at connection +time with exact origin and selected repository explanation. Tokens, private +evidence, code, drafts and browsing history are excluded from synchronized +preferences, exports, telemetry and diagnostics. No remote executable features, +custom scripts or arbitrary fetch/command messages are supported. + +## 12. Observability and operational UX + +Per-feature diagnostics show enabled/paused/unsupported/error, affected surface, +extension version, browser adapter and sanitized error code. They do not include +page text, draft contents, private paths or credentials. Explicit export previews +the sanitized report. Connected detail adds source/time/run link without bulk +logs. No network telemetry ships by default. Action Job Summaries remain inspectable +source evidence; future producer changes add a publication outcome and source +identity under I10 without extra timeline comments. + +## 13. Compatibility, migration, rollout, and rollback + +U features remain available with old/no Action. Connected schema compatibility is +I2; an unsupported major fails closed for C features. Existing native comments, +labels, drafts and checks are not migrated into extension ownership. + +Rollout sequence: internal unpacked builds on all three browsers → opt-in pilot +with public/private fixtures → beta stores/TestFlight → reviewed release across +the three targets. Each stage needs D8 evidence. Pausing one broken feature is +the first recovery; a reviewed compatible package/settings version is rollback. +Store version monotonicity may require publishing a higher version containing a +revert rather than installing an older signed version. Never promise immediate +store review or silently drop Safari to call the complete product shipped. + +## 14. Testing strategy and numeric budget + +**96 retained distinct core implementation cases**, covering foundational policy, lifecycle and evidence behavior. These are one part of the complete product budget: the functional catalog owns 659 additional cases and center/setup owns 48, for **803 distinct cases**. The core budget below is independently derived from +asynchronous DOM navigation, a new trust/compatibility contract and three browser +packages. This specification change does not create or claim these tests. + +| Area / case IDs | Minimum | Covered behavior inventory | Owner | +|---|---:|---|---| +| bex-F-C01–bex-F-C12 pure feature/configuration | 12 | eligibility by surface; defaults; pause precedence; repo identity/rename; invalid enum; unknown feature; oversized import; atomic migration; old schema; future schema; saved query precedence; nonconfigurable invariants | Product/platform | +| bex-N-C01–bex-N-C14 lifecycle/races | 14 | initial mount; soft navigation; partial refresh; back/forward; virtualized insertion; removal; dedup; request cancellation; late response; cross-repo response; two tabs; update generation; pause during work; bounded observer disposal | Platform | +| bex-A-C01–bex-A-C12 adapters/API | 12 | canonical issue; canonical PR; exact file SHA; ambiguous link; missing anchor; clipboard denied; 401; 403; masked 404; offline; 429/secondary limit; incomplete pagination | Platform/integration | +| bex-I-C01–bex-I-C16 Action contract | 16 | absent manifest; valid manifest; unknown major; malformed payload; untrusted author; foreign repo; missing native association; multiple PRs; superseded run; head changed; base/policy changed; stale time; partial coverage; corrupt counts; unknown capabilities; final identity fence | Integration | +| bex-V-C01–bex-V-C14 presentation/drafts | 14 | standalone; pending; action-required; blocked; partial; complete; stale; unavailable; EN/ES fallback; keyboard/focus; light/dark/zoom; editor preservation; append dedup; wrong-context copy fallback | Product | +| bex-S-C01–bex-S-C16 permissions/security | 16 | host allowlist; protected route; least privilege; session token isolation; secret redaction; origin/sender spoof; arbitrary fetch rejection; command injection; unsafe URL; hostile Markdown; export exclusion; account change; logout; revocation; private/incognito separation; remote-code prohibition | Platform/integration | +| bex-E-C01–bex-E-C12 packaging/migration/integration | 12 | Chrome load; Firefox load; Safari real extension load; worker suspension; event-page restart; API permission revoked; no-Action usability; mixed-version compatibility; settings rollback; uninstall cleanup; coexistence; performance budget | Platform | +| **Total** | **96** | Repeated matrix execution is not a new behavior | All | + +| Area | Minimum distinct cases | Behaviors/risks covered | +|---|---|---| +| Feature policies | 12 | See the observable F inventory rows below. | +| Navigation lifecycle | 14 | See the observable N inventory rows below. | +| Provider adapters | 12 | See the observable A inventory rows below. | +| Action evidence | 16 | See the observable I inventory rows below. | +| Presentation and drafts | 14 | See the observable V inventory rows below. | +| Security and permissions | 16 | See the observable S inventory rows below. | +| Packaging and integration | 12 | See the observable E inventory rows below. | +| Total | 96 | Retained core cases only; add 659 catalog and 48 center/setup cases for the 803-case product total. Matrix reruns do not add cases. | + +| Case ID | Area | Requirements | Scenario | +|---|---|---|---| +| bex-F-C01 | Feature policies | BEX-P1, BEX-P2 | Unsupported page mounts no feature and makes no API request. | +| bex-F-C02 | Feature policies | BEX-P1, BEX-P5 | Fresh settings resolve all shipped defaults without a credential. | +| bex-F-C03 | Feature policies | BEX-P5, BEX-P8 | Repository pause wins over an enabled global feature. | +| bex-F-C04 | Feature policies | BEX-P5 | Repository rename retains numeric-ID preferences without affecting another repository. | +| bex-F-C05 | Feature policies | BEX-P5 | Invalid setting enum is rejected with previous settings intact. | +| bex-F-C06 | Feature policies | BEX-P2, BEX-P5 | Unknown feature ID does not activate code or corrupt known preferences. | +| bex-F-C07 | Feature policies | BEX-P5, BEX-P9 | An import over 64 KiB is rejected before any settings write. | +| bex-F-C08 | Feature policies | BEX-P5, BEX-P9 | Interrupted migration retains the prior complete settings version. | +| bex-F-C09 | Feature policies | BEX-P5 | A supported old settings version migrates once with the same second-run result. | +| bex-F-C10 | Feature policies | BEX-P5 | A future settings schema remains read-only and exportable. | +| bex-F-C11 | Feature policies | BEX-P1, BEX-P6 | Opening a shared filtered link preserves its query until explicit Restore. | +| bex-F-C12 | Feature policies | BEX-P3, BEX-P4, BEX-P5 | An imported preference cannot enable auto-submission or weaken evidence checks. | +| bex-N-C01 | Navigation lifecycle | BEX-P6, BEX-P8 | Initial load creates one owned control set per eligible feature. | +| bex-N-C02 | Navigation lifecycle | BEX-P6, BEX-P8 | Soft navigation disposes the old page generation before mounting the new one. | +| bex-N-C03 | Navigation lifecycle | BEX-P6 | Partial React refresh restores one keyed control without rewriting native content. | +| bex-N-C04 | Navigation lifecycle | BEX-P6 | Back/forward restoration preserves native scroll and one extension generation. | +| bex-N-C05 | Navigation lifecycle | BEX-P6, BEX-P8 | A virtualized file insertion gets one helper with loaded-scope counts. | +| bex-N-C06 | Navigation lifecycle | BEX-P6, BEX-P8 | Removed native anchors release their owned observers and listeners. | +| bex-N-C07 | Navigation lifecycle | BEX-P4, BEX-P6 | Repeated initialization does not duplicate a button or draft request. | +| bex-N-C08 | Navigation lifecycle | BEX-P3, BEX-P8 | Navigation aborts pending reads and retires their generation. | +| bex-N-C09 | Navigation lifecycle | BEX-P3, BEX-P8 | A late response cannot restore a disposed page view. | +| bex-N-C10 | Navigation lifecycle | BEX-P3 | A previous repository response never renders in the new repository. | +| bex-N-C11 | Navigation lifecycle | BEX-P8 | Two tabs coalesce one target refresh within the shared request budget. | +| bex-N-C12 | Navigation lifecycle | BEX-P6, BEX-P9 | An extension update retires old owned controls and offers one refresh affordance. | +| bex-N-C13 | Navigation lifecycle | BEX-P5, BEX-P8 | Pausing during collection prevents further reads and DOM updates. | +| bex-N-C14 | Navigation lifecycle | BEX-P6, BEX-P8 | After twenty navigation cycles resource counts return to the declared disposal baseline. | +| bex-A-C01 | Provider adapters | BEX-P1, BEX-P6 | The copied issue URL identifies the observed canonical repository and issue. | +| bex-A-C02 | Provider adapters | BEX-P1, BEX-P6 | The PR helper links the exact observed PR without selecting a same-number issue. | +| bex-A-C03 | Provider adapters | BEX-P1, BEX-P6 | A file permalink contains the verified immutable commit and line anchor. | +| bex-A-C04 | Provider adapters | BEX-P1, BEX-P6 | Ambiguous references stay plain text rather than guessed links. | +| bex-A-C05 | Provider adapters | BEX-P1, BEX-P6 | Missing DOM anchor disables only the affected helper. | +| bex-A-C06 | Provider adapters | BEX-P1, BEX-P6 | Denied clipboard access offers selectable text without claiming copy success. | +| bex-A-C07 | Provider adapters | BEX-P3, BEX-P8 | A 401 clears protected credentials/evidence and exposes reconnect guidance. | +| bex-A-C08 | Provider adapters | BEX-P3, BEX-P8 | A 403 marks current connected evidence unavailable without broader access fallback. | +| bex-A-C09 | Provider adapters | BEX-P3 | A masked private 404 is unknown access, not proof the object does not exist. | +| bex-A-C10 | Provider adapters | BEX-P3, BEX-P8 | Offline refresh retains clearly historical source facts and creates no retry loop. | +| bex-A-C11 | Provider adapters | BEX-P8 | A secondary rate limit postpones requests until the provider or bounded backoff allows them. | +| bex-A-C12 | Provider adapters | BEX-P3, BEX-P8 | Incomplete pagination exposes partial scope and no aggregate zero or ready state. | +| bex-I-C01 | Action evidence | BEX-P1, BEX-P3 | Missing reviewed manifest leaves standalone features usable and connected mode off. | +| bex-I-C02 | Action evidence | BEX-P2, BEX-P3 | A valid pinned manifest and compatible source expose only declared capabilities. | +| bex-I-C03 | Action evidence | BEX-P2, BEX-P3 | A future schema major disables connected projections with upgrade guidance. | +| bex-I-C04 | Action evidence | BEX-P3, BEX-P9 | Malformed or duplicate-key source JSON is rejected before projection. | +| bex-I-C05 | Action evidence | BEX-P3, BEX-P9 | A copied marker from a different numeric author never becomes trusted evidence. | +| bex-I-C06 | Action evidence | BEX-P3 | Foreign repository/conversation identity is rejected despite matching display names. | +| bex-I-C07 | Action evidence | BEX-P3 | Missing explicit association does not invent an issue, branch or PR link. | +| bex-I-C08 | Action evidence | BEX-P3, BEX-P4 | Multiple reported linked PRs require a PR-specific view instead of choosing the newest. | +| bex-I-C09 | Action evidence | BEX-P3 | An older run attempt or generation cannot overwrite newer observed evidence. | +| bex-I-C10 | Action evidence | BEX-P3 | A changed head clears aggregate satisfaction and current finding counts. | +| bex-I-C11 | Action evidence | BEX-P3 | Changed base/public policy identity clears the prior aggregate; hidden live policy remains unknown. | +| bex-I-C12 | Action evidence | BEX-P3, BEX-P8 | Expired or future-skewed observation time yields stale/unavailable, not a current assessment. | +| bex-I-C13 | Action evidence | BEX-P3 | Partial review coverage preserves source facts but keeps the aggregate finding count unknown. | +| bex-I-C14 | Action evidence | BEX-P3, BEX-P9 | Inconsistent finding totals/items are rejected rather than rounded to zero. | +| bex-I-C15 | Action evidence | BEX-P2, BEX-P3 | Unsupported capability tokens never execute code or enable a command. | +| bex-I-C16 | Action evidence | BEX-P3, BEX-P8 | A final identity/page/credential fence rejects a response superseded during collection. | +| bex-V-C01 | Presentation and drafts | BEX-P1, BEX-P7 | Standalone view explains optional connection while U controls remain available. | +| bex-V-C02 | Presentation and drafts | BEX-P3, BEX-P7 | Pending view names completed facts, the active run and that no human action is required. | +| bex-V-C03 | Presentation and drafts | BEX-P3, BEX-P7 | Action-required view names the responsible actor and exact clarification destination. | +| bex-V-C04 | Presentation and drafts | BEX-P3, BEX-P7 | Blocked view follows impact, cause, action and retained-facts order. | +| bex-V-C05 | Presentation and drafts | BEX-P3, BEX-P7 | Partial view retains verified facts and omits overall readiness. | +| bex-V-C06 | Presentation and drafts | BEX-P3, BEX-P7 | Complete snapshot view includes assessed revision/time and preserves human-review obligations. | +| bex-V-C07 | Presentation and drafts | BEX-P3, BEX-P7 | Stale view separates the previous assessment from unknown current finding counts. | +| bex-V-C08 | Presentation and drafts | BEX-P3, BEX-P7 | Unavailable view links native GitHub and does not imply underlying Action work failed. | +| bex-V-C09 | Presentation and drafts | BEX-P7 | Unsupported locale falls back atomically to complete English while Spanish is complete. | +| bex-V-C10 | Presentation and drafts | BEX-P6, BEX-P7 | Keyboard focus survives refresh and all controls have accessible names. | +| bex-V-C11 | Presentation and drafts | BEX-P7 | Light/dark, high contrast, 200 percent zoom and narrow layout retain readable actions. | +| bex-V-C12 | Presentation and drafts | BEX-P4, BEX-P6, BEX-P7 | Keeping or canceling a prepared request preserves every existing native draft byte. | +| bex-V-C13 | Presentation and drafts | BEX-P4, BEX-P6 | Append request happens once despite rerender and leaves submission to the user. | +| bex-V-C14 | Presentation and drafts | BEX-P4, BEX-P7 | Unsupported correction context offers an exact copy-only destination without inserting a broad request. | +| bex-S-C01 | Security and permissions | BEX-P8, BEX-P9 | An unapproved host or cross-origin redirect receives no credential or provider request. | +| bex-S-C02 | Security and permissions | BEX-P8, BEX-P9 | Protected login/token/settings routes install no private observers or connected reads. | +| bex-S-C03 | Security and permissions | BEX-P1, BEX-P9 | Standalone installation requests no API write or blanket host permission. | +| bex-S-C04 | Security and permissions | BEX-P9 | Content scripts cannot retrieve the protected session token through storage or messages. | +| bex-S-C05 | Security and permissions | BEX-P9 | Token-bearing diagnostics are redacted and no raw credential is returned to a view. | +| bex-S-C06 | Security and permissions | BEX-P3, BEX-P9 | Forged origin/frame/tab sender fails before any semantic read operation. | +| bex-S-C07 | Security and permissions | BEX-P8, BEX-P9 | An arbitrary URL/method/body message is rejected by the closed background protocol. | +| bex-S-C08 | Security and permissions | BEX-P4, BEX-P9 | A finding operand containing command separators or line breaks cannot create a mutation draft. | +| bex-S-C09 | Security and permissions | BEX-P3, BEX-P9 | Unsafe source URLs render as unavailable text rather than executable links. | +| bex-S-C10 | Security and permissions | BEX-P6, BEX-P9 | Hostile Markdown/HTML cannot inject DOM, executable selectors or control text. | +| bex-S-C11 | Security and permissions | BEX-P5, BEX-P9 | Settings/diagnostic export excludes tokens, private evidence and human draft contents. | +| bex-S-C12 | Security and permissions | BEX-P3, BEX-P9 | Account change invalidates the old epoch before clearing its credential and cache. | +| bex-S-C13 | Security and permissions | BEX-P3, BEX-P9 | Observed logout/different-viewer signal pauses connection without claiming the PAT was revoked. | +| bex-S-C14 | Security and permissions | BEX-P3, BEX-P9 | Revocation blocks late responses from repopulating cleared private session state. | +| bex-S-C15 | Security and permissions | BEX-P9 | Private browsing refuses connected operation and retains no navigation evidence. | +| bex-S-C16 | Security and permissions | BEX-P2, BEX-P9 | Bundle/manifest checks reject remote executable code and undeclared permission expansion. | +| bex-E-C01 | Packaging and integration | BEX-P2, BEX-P9 | Chrome loads the exact generated artifact and exercises all eligible registered product capabilities. | +| bex-E-C02 | Packaging and integration | BEX-P2, BEX-P9 | Firefox loads the target artifact on stable and selected ESR with the same semantics. | +| bex-E-C03 | Packaging and integration | BEX-P2, BEX-P9 | A real Safari containing-app extension is enabled and exercised; generic WebKit cannot substitute. | +| bex-E-C04 | Packaging and integration | BEX-P3, BEX-P8 | Chrome worker suspension resumes with session state or an explicit disconnect and fresh identity read. | +| bex-E-C05 | Packaging and integration | BEX-P3, BEX-P8 | Firefox/Safari event-page restart does not rely on persistent process globals. | +| bex-E-C06 | Packaging and integration | BEX-P1, BEX-P8, BEX-P9 | Optional API site-access revocation aborts reads while standalone U features remain usable. | +| bex-E-C07 | Packaging and integration | BEX-P1, BEX-P2 | A repository without Copilot still provides standalone functionality without a token. | +| bex-E-C08 | Packaging and integration | BEX-P2, BEX-P3, BEX-P9 | Old/no/future producer versions retain standalone use and disclose connected compatibility. | +| bex-E-C09 | Packaging and integration | BEX-P5, BEX-P9 | Reviewed code/settings rollback restores a compatible view without credential backup. | +| bex-E-C10 | Packaging and integration | BEX-P6, BEX-P9 | Disable/uninstall releases owned resources and session secrets without repository side effects. | +| bex-E-C11 | Packaging and integration | BEX-P6, BEX-P9 | A native/other-extension equivalent prevents duplicate helpers and leaves original controls intact. | +| bex-E-C12 | Packaging and integration | BEX-P8, BEX-P9 | Measured startup, DOM, retained-memory and request work meets the published budgets. | + +Keep existing repository thresholds. New pure evidence/authorization decisions +require 100% branch coverage; other changed modules retain applicable budgets. +Use fake clocks/IDs/providers, deterministic HTML/API fixtures, semantic UI +assertions and schema/manifest/dependency parsing, not only snapshots or grep. +bex-E-C03 requires actual Safari-extension evidence; generic WebKit does not suffice. +D8 supplies the browser/OS matrix, real screen-reader/keyboard/theme artifacts and +performance measurement procedure. Every behavior inventory item above has a +stable case ID; matrix permutations are recorded separately. + +## 15. Documentation and discoverability + +These are implementation deliverables; this specification does not publish an +installation claim in user docs. Add a **docs/browser-extension/** navigation group +in `docs.json` only when its linked files exist and clearly carry availability. + +| Audience | Planned artifact | Required content / validation | +|---|---|---| +| User | `docs/browser-extension/index.mdx`, `features.mdx` | Standalone → optional connected journey, feature defaults, visual/text example; links checked | +| Setup owner | `installation.mdx`, `permissions.mdx` | Three store/dev install paths, optional read token, repository manifest, no bot token; fixture-checked examples | +| User | `configuration.mdx`, `privacy.mdx` | Complete bounds/precedence, export/reset, session data, no telemetry; settings schema fixtures | +| Operator | `troubleshooting.mdx`, `compatibility.mdx` | Unavailable/stale/partial, revoke, pause, upgrade/rollback, browser table; recovery fixture links | +| Contributor | `architecture.mdx`, `action-contract.mdx` | Ports, trust, schema ownership and tests; executable boundary/schema checks | + +Also update README discoverability and the existing Action status/command docs +when compatible producer support actually ships. Run repository documentation, +asset/frontmatter, navigation and specification checks for changed artifacts. + + +Publication inventory relative to the PR base develop: all five extension specifications are created by this PR. The Action first created the primary file in its initial SDD commit, then contributor commits expanded it; the PR-level Change column therefore says create. This is a full-product change plan relative to that base, not a claim that every row ships in this specification PR. README, docs.json and future user-documentation paths +are explicit design deliverables, not files shipped by this specification PR. + +| Path | Change | +|---|---| +| specs/github-browser-extension.md | create | +| specs/github-browser-extension-action-integration.md | create | +| specs/github-browser-extension-platforms-and-delivery.md | create | +| specs/github-browser-extension-functional-catalog.md | create | +| specs/github-browser-extension-control-center-and-setup.md | create | +| specs/browser-extension/feature-catalog.v1.json | create | +| specs/browser-extension/feature-catalog.schema.json | create | +| specs/browser-extension/feature-catalog-index.schema.json | create | +| specs/browser-extension/features/NAV.v1.json | create | +| specs/browser-extension/features/CODE.v1.json | create | +| specs/browser-extension/features/REVIEW.v1.json | create | +| specs/browser-extension/features/ISSUE.v1.json | create | +| specs/browser-extension/features/SEARCH.v1.json | create | +| specs/browser-extension/features/NOTIFY.v1.json | create | +| specs/browser-extension/features/CI.v1.json | create | +| specs/browser-extension/features/RELEASE.v1.json | create | +| specs/browser-extension/features/WORK.v1.json | create | +| specs/browser-extension/features/COPILOT.v1.json | create | +| specs/browser-extension/features/CENTER.v1.json | create | +| specs/browser-extension/features/SETUP.v1.json | create | +| specs/browser-extension/requests-v2.schema.json | create | +| specs/browser-extension/examples/requests-v2.json | create | +| scripts/validate-browser-extension-specifications.cjs | create | +| test-support/browser-extension-specifications.test.cjs | create | +| package.json | update | +| pnpm-lock.yaml | update | +| specs/local-web-setup-assistant.md | update | +| specs/setup-configuration-management.md | update | +| specs/catalog.json | update | +| specs/CATALOG.md | update | +| docs.json | update | +| README.md | update | +| specs/browser-extension/status-v1.schema.json | create | +| specs/browser-extension/manifest-v1.schema.json | create | +| specs/browser-extension/examples/status-invalid-head-v1.json | create | +| specs/browser-extension/examples/manifest-v1.json | create | +| specs/browser-extension/examples/status-pr-v1.json | create | +| specs/browser-extension/examples/status-issue-v1.json | create | +| docs/browser-extension/index.mdx | create | +| docs/browser-extension/features.mdx | create | +| docs/browser-extension/installation.mdx | create | +| docs/browser-extension/permissions.mdx | create | +| docs/browser-extension/configuration.mdx | create | +| docs/browser-extension/privacy.mdx | create | +| docs/browser-extension/troubleshooting.mdx | create | +| docs/browser-extension/compatibility.mdx | create | +| docs/browser-extension/architecture.mdx | create | +| docs/browser-extension/action-contract.mdx | create | + +## 16. Acceptance scenarios + +1. Install with no token/Action: U1–U6 work; connected panel offers explicit setup. +2. Open a shared issue filter: its query remains unchanged until Restore is chosen. +3. Hide generated files: show count and Restore all; native required action stays. +4. Navigate/back while context loads: one owned control set; old response discarded. +5. Current compatible Action assessment: show exact identity/time/source and next + actor; no claim that the extension authorizes merge. +6. New head/partial findings/denied source: no zero count or overall ready state. +7. Prepare fix in unsupported context: copy-only guidance to a verified location; + no broad issue comment that pretends to target a branch. +8. Existing native draft: retain bytes on cancel/keep; append once; no submission. +9. Pause/disconnect: stop requests and remove owned enhancements/session evidence; + native GitHub and repository state are unchanged. +10. All browser matrix cases and human evidence meet D8 before complete product acceptance; + a missing Safari result is a release blocker, not a generic WebKit substitute. + +## 17. Requirements traceability + +| Requirement | Owning policy/use case/adapter/presentation | Verification | Documentation | +|---|---|---|---| +| P1 | Feature eligibility, page adapters | bex-F-C01–bex-F-C02, bex-A-C01–bex-A-C06, bex-E-C07 | index/features | +| P2 | Feature registry/catalog and package gates | bex-F-C06, bex-E-C01–bex-E-C03, D8 review | features/compatibility | +| P3 | I1–I7 evidence reader, context/findings VM | bex-I-C01–bex-I-C16, bex-V-C02–bex-V-C08 | action-contract/troubleshooting | +| P4 | DraftRequest and NativeComposer port | bex-V-C12–bex-V-C14, bex-S-C08, I8 acceptance | features/permissions | +| P5 | Settings/pause/migration use cases | bex-F-C03–bex-F-C12, bex-N-C13, bex-E-C09–bex-E-C10 | configuration/privacy | +| P6 | Feature lifecycle and renderers | bex-N-C01–bex-N-C14, bex-V-C10–bex-V-C12, bex-E-C11 | features/troubleshooting | +| P7 | Catalog/render/focus policies | bex-V-C01–bex-V-C14, D8 human matrix | features/compatibility | +| P8 | Request scheduler, observer budget | bex-A-C07–bex-A-C12, bex-E-C04–bex-E-C06/bex-E-C12 | privacy/troubleshooting | +| P9 | Build/schema/import/store gates | bex-S-C01–bex-S-C16, bex-E-C01–bex-E-C12 and doc validation | architecture/installation | + +| Requirement | Cases | +|---|---| +| BEX-P1 | bex-F-C01, bex-F-C02, bex-F-C11, bex-A-C01, bex-A-C02, bex-A-C03, bex-A-C04, bex-A-C05, bex-A-C06, bex-I-C01, bex-V-C01, bex-S-C03, bex-E-C06, bex-E-C07 | +| BEX-P2 | bex-F-C01, bex-F-C06, bex-I-C02, bex-I-C03, bex-I-C15, bex-S-C16, bex-E-C01, bex-E-C02, bex-E-C03, bex-E-C07, bex-E-C08 | +| BEX-P3 | bex-F-C12, bex-N-C08, bex-N-C09, bex-N-C10, bex-A-C07, bex-A-C08, bex-A-C09, bex-A-C10, bex-A-C12, bex-I-C01, bex-I-C02, bex-I-C03, bex-I-C04, bex-I-C05, bex-I-C06, bex-I-C07, bex-I-C08, bex-I-C09, bex-I-C10, bex-I-C11, bex-I-C12, bex-I-C13, bex-I-C14, bex-I-C15, bex-I-C16, bex-V-C02, bex-V-C03, bex-V-C04, bex-V-C05, bex-V-C06, bex-V-C07, bex-V-C08, bex-S-C06, bex-S-C09, bex-S-C12, bex-S-C13, bex-S-C14, bex-E-C04, bex-E-C05, bex-E-C08 | +| BEX-P4 | bex-F-C12, bex-N-C07, bex-I-C08, bex-V-C12, bex-V-C13, bex-V-C14, bex-S-C08 | +| BEX-P5 | bex-F-C02, bex-F-C03, bex-F-C04, bex-F-C05, bex-F-C06, bex-F-C07, bex-F-C08, bex-F-C09, bex-F-C10, bex-F-C12, bex-N-C13, bex-S-C11, bex-E-C09 | +| BEX-P6 | bex-F-C11, bex-N-C01, bex-N-C02, bex-N-C03, bex-N-C04, bex-N-C05, bex-N-C06, bex-N-C07, bex-N-C12, bex-N-C14, bex-A-C01, bex-A-C02, bex-A-C03, bex-A-C04, bex-A-C05, bex-A-C06, bex-V-C10, bex-V-C12, bex-V-C13, bex-S-C10, bex-E-C10, bex-E-C11 | +| BEX-P7 | bex-V-C01, bex-V-C02, bex-V-C03, bex-V-C04, bex-V-C05, bex-V-C06, bex-V-C07, bex-V-C08, bex-V-C09, bex-V-C10, bex-V-C11, bex-V-C12, bex-V-C14 | +| BEX-P8 | bex-F-C03, bex-N-C01, bex-N-C02, bex-N-C05, bex-N-C06, bex-N-C08, bex-N-C09, bex-N-C11, bex-N-C13, bex-N-C14, bex-A-C07, bex-A-C08, bex-A-C10, bex-A-C11, bex-A-C12, bex-I-C12, bex-I-C16, bex-S-C01, bex-S-C02, bex-S-C07, bex-E-C04, bex-E-C05, bex-E-C06, bex-E-C12 | +| BEX-P9 | bex-F-C07, bex-F-C08, bex-N-C12, bex-I-C04, bex-I-C05, bex-I-C14, bex-S-C01, bex-S-C02, bex-S-C03, bex-S-C04, bex-S-C05, bex-S-C06, bex-S-C07, bex-S-C08, bex-S-C09, bex-S-C10, bex-S-C11, bex-S-C12, bex-S-C13, bex-S-C14, bex-S-C15, bex-S-C16, bex-E-C01, bex-E-C02, bex-E-C03, bex-E-C06, bex-E-C08, bex-E-C09, bex-E-C10, bex-E-C11, bex-E-C12 | + +## 18. Implementation sequence + +1. Review the complete five-SDD contract, 150-function catalog, 803-case acceptance inventory and explicit authority/architecture constraints. +2. Build the full local center, shared setup presentation/contracts and portable feature registry with real three-browser harnesses. +3. Deliver native navigation/code/review/issue/search/notification/Actions/release/workspace families in dependency-sized increments, with tests and docs together. +4. Deliver the versioned Action producer/evidence reader, complete compatible command catalog, findings/SDD/lifecycle/recovery views and exact-context native drafts. +5. Deliver closed optional user-write operations and shared setup inspector/quick adjustments/full wizard/batch/doctor with protected credential/Apply handoff. +6. Complete every required function, four locales, accessibility, performance/security/partial-state acceptance, signed artifacts and full documentation. +7. Audit all 150 functions and all 803 distinct cases plus the actual browser/OS/version evidence before general product acceptance. Work waves do not constitute reduced product scopes. + +## 19. Definition of Done + +For this specification issue: five linked decision-complete SDDs and the complete structured functional catalog, proposed +catalog evidence, a generated catalog, valid links and passing specification +checks; no runtime claim. Product/architecture/security review remains explicit. + +For future implementation: +- [ ] P1–P9 and I/D companion requirements have acceptance evidence and traceability. +- [ ] Architecture, manifests, schemas and package constraints are executable. +- [ ] All 803 distinct core/feature/center cases, coverage budgets and real three-browser/OS matrix pass. +- [ ] Bounds/defaults/settings migration and recovery match this contract. +- [ ] Primary states, draft preservation, accessibility and complete EN/ES/FR/PT pass. +- [ ] Failure/races/security/privacy/cleanup and zero unsolicited writes pass. +- [ ] User/setup/operator/contributor docs exist and navigation is validated. +- [ ] Platform accounts/signing and store readiness have named maintainer owners. +- [ ] Catalog evidence distinguishes specification, implementation and live proof. +- [ ] `pnpm run generate:specifications` and `pnpm run validate:specifications` pass. +- [ ] No material architecture/public behavior/data safety decision remains open. + +## 20. References and decisions + +Decisions: complete 150-function desktop product; packaged full-page local center; shared original setup presentation and one CLI-owned privileged engine; all current compatible Action request families; bounded read/native draft/reviewed optional write separation; one trustworthy producer contract; and real accessibility/security/performance/documentation/browser acceptance. No reduced feature inventory can satisfy final acceptance. Primary sources and implementation constraints are in the companions. All code, selectors, assets, UX and prose are independently authored. + +The original 96 core cases keep their stable identifiers and observable intent. Product scope is expanded by the additional structured feature and center/setup inventories; implementation evidence remains distinct from this specification. + +The expanded specification retains all 96 case identities from the Action-published inventory for issue #694. The detailed BEX-P requirements refine the three initial grouping requirements; all retained cases keep their observable scenario intent. diff --git a/specs/local-web-setup-assistant.md b/specs/local-web-setup-assistant.md index c5aed2829..1e1138dc9 100644 --- a/specs/local-web-setup-assistant.md +++ b/specs/local-web-setup-assistant.md @@ -2970,3 +2970,9 @@ successful fresh Windows run on the reviewed head, alongside the other platform jobs. Existing parsed workflow-contract checks cover this configuration change; no new application behavior or test count is introduced. Contributor guidance is in docs/development/testing.mdx; no consumer setting or migration is added. + +## Extension control-center integration proposal (2026-10-25) + +The [browser-extension local center and setup contract](github-browser-extension-control-center-and-setup.md) specifies a prospective additional consumer of the shared presentation and nonsecret setup contracts. It is not evidence that the current CLI/server implements an extension protocol. The existing same-origin Host/CSP/pairing/controller/credential/final-approval and cleanup guards remain normative. In particular, do not embed this page in an iframe, weaken CORS, export its session key or let an extension submit privileged approval/credentials through a generic answer proxy. + +Future implementation extracts browser-safe original Svelte components/catalogs and introduces a separate closed nonsecret broker adapter with revision/role fencing, while the CLI/application engine remains authoritative. Credential entry and final Apply stay in the trusted terminal/local-web authority; the extension may prepare choices and observe sanitized progress. Shared fixture/packaged browser tests must prove CLI/web/extension policy, question, plan, permission and recovery parity before acceptance. The extension specification includes 48 dedicated cross-boundary cases in addition to its per-feature cases; these are future tests, not current runtime proof. Existing CLI defaults and standalone local-web operation remain compatibility gates. diff --git a/specs/setup-configuration-management.md b/specs/setup-configuration-management.md index f21fe0328..2a0a5a4cd 100644 --- a/specs/setup-configuration-management.md +++ b/specs/setup-configuration-management.md @@ -358,3 +358,9 @@ Evidence: `setup_organization_import_wizard.test.ts`, `setup_trusted_health_sdk_contract.integration.test.ts`, and `web_setup_batch_components.test.ts`. Owning test budget, migration, UX and operational acceptance are in the companion; existing quality gates remain. + +## Extension control-center integration proposal (2026-10-25) + +The [browser-extension local center and setup contract](github-browser-extension-control-center-and-setup.md) specifies a prospective additional consumer of the shared presentation and nonsecret setup contracts. It is not evidence that the current CLI/server implements an extension protocol. The existing same-origin Host/CSP/pairing/controller/credential/final-approval and cleanup guards remain normative. In particular, do not embed this page in an iframe, weaken CORS, export its session key or let an extension submit privileged approval/credentials through a generic answer proxy. + +Future implementation extracts browser-safe original Svelte components/catalogs and introduces a separate closed nonsecret broker adapter with revision/role fencing, while the CLI/application engine remains authoritative. Credential entry and final Apply stay in the trusted terminal/local-web authority; the extension may prepare choices and observe sanitized progress. Shared fixture/packaged browser tests must prove CLI/web/extension policy, question, plan, permission and recovery parity before acceptance. The extension specification includes 48 dedicated cross-boundary cases in addition to its per-feature cases; these are future tests, not current runtime proof. Existing CLI defaults and standalone local-web operation remain compatibility gates. diff --git a/test-support/browser-extension-specifications.test.cjs b/test-support/browser-extension-specifications.test.cjs new file mode 100644 index 000000000..6ec387a9e --- /dev/null +++ b/test-support/browser-extension-specifications.test.cjs @@ -0,0 +1,109 @@ +const { test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const { validate, validateFeatures, validateFeatureTraceability, validateRequests, compiler, readJson, loadFeatureCatalog } = require('../scripts/validate-browser-extension-specifications.cjs'); + +const root = path.resolve(__dirname, '..'); +const featureSchema = compiler(root, 'feature-catalog.schema.json'); +const requestSchema = compiler(root, 'requests-v2.schema.json'); +const features = () => loadFeatureCatalog(root); +const requests = () => readJson(root, 'examples/requests-v2.json'); +const names = requests().commands.map(command => command.name); + +test('validates the complete proposed catalog, real schemas/fixtures and document ownership', () => { + assert.deepEqual(validate(root), { features: 150, commands: 21, cases: 803, schemas: 5, positiveFixtures: 6, expectedNegativeFixtures: 1 }); +}); + +test('rejects catalog references outside the fixed local family directory', () => { + const index = readJson(root, 'feature-catalog.v1.json'); index.families[0].file = '../../outside.json'; + assert.throws(() => loadFeatureCatalog(root, index), /feature index violates its JSON schema/); +}); + +test('rejects swapping a valid family path into another family slot', () => { + const index = readJson(root, 'feature-catalog.v1.json'); index.families[0].file = index.families[1].file; + assert.throws(() => loadFeatureCatalog(root, index), /family path mismatch/); +}); + +test('rejects duplicate capabilities instead of counting the same feature twice', () => { + const value = features(); value.families[0].features[1] = structuredClone(value.families[0].features[0]); + assert.throws(() => validateFeatures(value, featureSchema), /feature IDs must be unique/); +}); + +test('rejects reused case identities despite an unchanged total', () => { + const value = features(); value.families[0].features[0].tests[1].id = value.families[0].features[0].tests[0].id; + assert.throws(() => validateFeatures(value, featureSchema), /feature case IDs must be unique/); +}); + +test('rejects reclassifying a required product function as deferred', () => { + const value = features(); value.families[0].features[0].delivery = 'future'; + assert.throws(() => validateFeatures(value, featureSchema), /JSON schema/); +}); + +test('rejects dropping Safari from a registered function', () => { + const value = features(); value.families[0].features[0].browsers = ['chrome', 'firefox']; + assert.throws(() => validateFeatures(value, featureSchema), /JSON schema/); +}); + +test('rejects credential-shaped unknown metadata in the closed catalog', () => { + const value = features(); value.families[0].features[0].token = 'fixture-only-not-a-credential'; + assert.throws(() => validateFeatures(value, featureSchema), /JSON schema/); +}); + +test('rejects a feature detached from its family requirement', () => { + const value = features(); value.families[0].features[0].requirements = ['CAT-CODE']; + assert.throws(() => validateFeatures(value, featureSchema), /requirement mismatch/); +}); + +test('rejects replacing write-risk cases with a lower allocation', () => { + const value = features(); const item = value.families.flatMap(family => family.features).find(feature => feature.mode === 'write'); item.tests.pop(); + assert.throws(() => validateFeatures(value, featureSchema), /risk-case allocation mismatch/); +}); + +test('rejects stale per-family case counts in readable requirement traceability', () => { + const text = fs.readFileSync(path.join(root, 'specs/github-browser-extension-functional-catalog.md'), 'utf8'); + const stale = text.replace(/(\| CAT-NOTIFY \|[^\n]+\| )32 explicit cases/, (_, prefix) => `${prefix}29 explicit cases`); + assert.notEqual(stale, text); + assert.throws(() => validateFeatureTraceability(features(), stale), /CAT-NOTIFY case traceability mismatch/); +}); + +for (const suffix of ['', ' with conflicting cells']) { + test(`rejects duplicate feature traceability rows${suffix}`, () => { + const text = fs.readFileSync(path.join(root, 'specs/github-browser-extension-functional-catalog.md'), 'utf8'); + const row = text.split('\n').find(line => line.startsWith('| CAT-NOTIFY |') && line.includes('explicit cases')); + const duplicate = suffix ? row.replace('32 explicit cases in the JSON test inventory', 'unavailable cases') : row; + const duplicated = text.replace('## 18. Implementation sequence', `${duplicate}\n\n## 18. Implementation sequence`); + assert.throws(() => validateFeatureTraceability(features(), duplicated), /CAT-NOTIFY must have exactly one/); + }); +} + +for (const outerPipes of [true, false]) { + test(`rejects conflicting compact Markdown rows with outer pipes ${outerPipes}`, () => { + const text = fs.readFileSync(path.join(root, 'specs/github-browser-extension-functional-catalog.md'), 'utf8'); + const row = text.split('\n').find(line => line.startsWith('| CAT-NOTIFY |') && line.includes('explicit cases')); + let compact = row.replace(/\s*\|\s*/g, '|').replace('32 explicit cases', '29 explicit cases'); + if (!outerPipes) compact = compact.slice(1, -1); + const duplicated = text.replace('## 18. Implementation sequence', `${compact}\n\n## 18. Implementation sequence`); + assert.throws(() => validateFeatureTraceability(features(), duplicated), /CAT-NOTIFY must have exactly one/); + }); +} + +test('rejects weakening finding-dismissal actor authorization', () => { + const value = requests(); value.commands.find(command => command.name === 'dismiss').requiresWriteActor = false; + assert.throws(() => validateRequests(value, requestSchema, names), /write-actor guard/); +}); + +test('rejects a fabricated command outside the reviewed grammar', () => { + const value = requests(); value.commands[0].name = 'deploy-now'; + assert.throws(() => validateRequests(value, requestSchema, names), /JSON schema/); +}); + +test('rejects broadening file-changing command routes in the fixture', () => { + const value = requests(); value.commands.find(command => command.name === 'implement').contexts.push('conversation'); + assert.throws(() => validateRequests(value, requestSchema, names), /authoritative route/); +}); + +test('rejects classifying a model-running command as model-free', () => { + const value = requests(); value.commands.find(command => command.name === 'findings').agent = 'never'; + assert.throws(() => validateRequests(value, requestSchema, names), /agent classification mismatch/); +});