From eab9840c143432b67db247af858ba2ff8b8da524 Mon Sep 17 00:00:00 2001 From: StoneHub Date: Sat, 25 Jul 2026 10:42:04 -0400 Subject: [PATCH 1/3] Prepare v1.7 Browser Code UX --- CHANGELOG.md | 11 +- QUICKSTART.md | 4 +- README.md | 6 +- content.js | 100 ++++- docs/chrome-web-store-submission-draft.md | 21 +- docs/icon-options.html | 485 ++++++++++++++++++++++ docs/manual-release-checklist.md | 12 +- docs/v1.7-product-plan.html | 461 ++++++++++++++++++++ generate-icons.html | 95 ++--- icon-source.svg | 17 + icon128.png | Bin 2383 -> 2811 bytes icon16.png | Bin 529 -> 437 bytes icon48.png | Bin 1213 -> 1135 bytes manifest.json | 4 +- mcp/server.mjs | 2 +- package-lock.json | 4 +- package.json | 2 +- product.json | 8 +- scripts/generate-icons.ps1 | 83 ++-- styles.css | 11 + test/mcp.test.mjs | 4 +- test/release.test.cjs | 5 + 22 files changed, 1193 insertions(+), 142 deletions(-) create mode 100644 docs/icon-options.html create mode 100644 docs/v1.7-product-plan.html create mode 100644 icon-source.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 643e8bc..1fb6361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,20 @@ # Changelog -## 1.6.0 (In development) +## 1.7.0 (Release candidate) + +- Replaced the generic speech-bubble icon with the Browser Code mark across packaged 16, 48, and 128 pixel assets. +- Anchored the collapsed in-page change list to the nearest viewport edge while preserving drag movement around the viewport perimeter. +- Replaced ambiguous plus/minus controls with explicit up/down chevrons and clearer accessible labels. +- Added the v1.7 product, Store-listing, and monetization plan plus reusable icon-choice source assets. + +## 1.6.0 (Published July 20, 2026) - Added a project-scoped local MCP companion over stdio with list, get, create, import, evidence, implementation-brief, and revision-checked status tools. - Added an ignored `.dev-feedback` sidecar with atomic JSON records, an append-only event trail, validated local evidence, and explicit project/inbox path boundaries. - Reused the existing History JSON export as the first explicit extension-to-agent handoff without reading Chromium internals, opening a localhost port, or adding extension permissions. - Kept source editing and browser control outside the MCP server; the connected coding agent uses its existing project tools and records bounded implementation status separately. -## 1.5.0 (Unreleased) +## 1.5.0 (Source checkpoint) - Added Visual Edit Mode for reversible move, resize, leaf-text rewrite, hide, sibling reorder, curated style, match-style, and alignment previews. - Added bounded undo/redo and guaranteed page restoration on Save, Cancel, mode exit, and navigation. diff --git a/QUICKSTART.md b/QUICKSTART.md index e61ccfc..5762bea 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -2,7 +2,7 @@ Get Dev Feedback Capture running in a few minutes. -The latest published ZIP is v1.2.0. The local MCP companion is in development in the v1.6 source checkout; Visual Edit Mode, the annotated Region editor, and the AI Bundle remain unreleased source features. +Chrome Web Store v1.6 is public. This source checkout prepares v1.7; the latest GitHub Release ZIP remains v1.2.0 until the deferred browser and agent-handoff gates are completed and recorded. ## 1. Load the extension @@ -25,7 +25,7 @@ Optional for local PDFs: 3. Leave the mode on `Element`. 4. Click `Start Element Mode` or press `Ctrl+Shift+F` (`Command+Shift+F` on macOS). 5. Click a page element, add your note, and save it. -6. The in-page capture list starts collapsed. Use **+** to expand it and **−** to collapse it again. +6. The in-page capture list starts collapsed and stays on the nearest viewport edge as you drag it. Use **⌃** to expand it and **⌄** to collapse it again. ## 3. Preview a visual edit diff --git a/README.md b/README.md index 2515d16..208d8d0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Dev Feedback Capture is a local-first Chromium extension that turns live pages, PDFs, and browser-visible surfaces into implementation-ready visual change specifications. It supports three workflows: -> The source checkout contains the in-development v1.6 local MCP companion on top of the unreleased v1.5 Visual Edit work. The latest published download remains v1.2.0 until the deferred browser and agent-handoff gates are complete. +> Chrome Web Store v1.6 is public. This source checkout prepares v1.7; the latest GitHub Release ZIP remains v1.2.0 until the deferred browser and agent-handoff gates are completed and recorded. - `Element` mode injects a lightweight in-page UI so you can click DOM elements and save selectors, styles, and notes. - `Visual` mode temporarily moves, resizes, rewrites, hides, reorders, or restyles one live DOM element, records original versus proposed intent, and restores the page after Save or Cancel. @@ -55,7 +55,7 @@ Use this path when developing the extension or reviewing source changes: 3. Click `Start Element Mode` or use `Ctrl+Shift+F` (`Command+Shift+F` on macOS). 4. Hover and click a page element. 5. Add your note in the modal and save it. -6. Use **+** on the compact capture chip to expand the saved-item list and **−** to collapse it again. +6. Drag the compact capture chip along the viewport edge, then use **⌃** to expand the saved-item list and **⌄** to collapse it again. ### Region Mode @@ -147,7 +147,7 @@ The extension does not use static host permissions, always-on content scripts, t 1. Confirm `package.json` and `manifest.json` versions match. 2. Run `npm test`, `npm run check`, and `npm run package`. `npm test` covers both extension and MCP contracts. -3. Complete the manual unpacked-extension and MCP handoff gates in `docs/manual-release-checklist.md`, then create and push a matching tag such as `v1.6.0`. +3. Complete the manual unpacked-extension and MCP handoff gates in `docs/manual-release-checklist.md`, then create and push the matching `v1.7.0` tag. 4. The release workflow builds `dist/dev-feedback-capture-v.zip` and publishes it as a GitHub Release asset. See [CHANGELOG.md](CHANGELOG.md) for release notes. diff --git a/content.js b/content.js index f457681..a5b2e35 100644 --- a/content.js +++ b/content.js @@ -64,6 +64,7 @@ let currentElement = null; let isDragging = false; let panelCollapsed = true; + let panelAnchor = 'right'; let dragOffset = { x: 0, y: 0 }; let feedbackPanel = null; let captureModal = null; @@ -108,7 +109,7 @@ V*
- +
@@ -238,11 +239,17 @@ panelCollapsed = !panelCollapsed; feedbackPanel.classList.toggle('collapsed', panelCollapsed); const button = feedbackPanel.querySelector('#dev-feedback-panel-toggle'); - button.textContent = panelCollapsed ? '+' : '−'; - button.title = panelCollapsed ? 'Expand capture list' : 'Collapse capture list'; + button.textContent = panelCollapsed ? '⌃' : '⌄'; + button.title = panelCollapsed ? 'Expand changes' : 'Collapse changes'; button.setAttribute('aria-label', button.title); button.setAttribute('aria-expanded', String(!panelCollapsed)); - window.requestAnimationFrame(clampPanelToViewport); + window.requestAnimationFrame(() => { + if (panelCollapsed) { + anchorPanelToViewportEdge(); + } else { + clampPanelToViewport(); + } + }); } function setPanelCollapsed(collapsed) { @@ -344,6 +351,46 @@ feedbackPanel.style.bottom = 'auto'; } + function getAnchoredPanelPosition(x, y, width, height, preferredEdge = null) { + const inset = 8; + const maxX = Math.max(inset, window.innerWidth - width - inset); + const maxY = Math.max(inset, window.innerHeight - height - inset); + const clampedX = clamp(x, inset, maxX); + const clampedY = clamp(y, inset, maxY); + const distances = { + left: clampedX - inset, + right: maxX - clampedX, + top: clampedY - inset, + bottom: maxY - clampedY + }; + const edge = preferredEdge && Object.hasOwn(distances, preferredEdge) + ? preferredEdge + : Object.entries(distances).sort((left, right) => left[1] - right[1])[0][0]; + + return { + edge, + x: edge === 'left' ? inset : edge === 'right' ? maxX : clampedX, + y: edge === 'top' ? inset : edge === 'bottom' ? maxY : clampedY + }; + } + + function anchorPanelToViewportEdge(preferredEdge = null) { + const rect = feedbackPanel.getBoundingClientRect(); + const position = getAnchoredPanelPosition( + rect.left, + rect.top, + rect.width, + rect.height, + preferredEdge + ); + panelAnchor = position.edge; + feedbackPanel.dataset.anchor = panelAnchor; + feedbackPanel.style.left = `${position.x}px`; + feedbackPanel.style.top = `${position.y}px`; + feedbackPanel.style.right = 'auto'; + feedbackPanel.style.bottom = 'auto'; + } + function createCaptureModal() { captureModal = document.createElement('div'); captureModal.id = UI_IDS.modal; @@ -391,7 +438,7 @@ } function attachGlobalListeners() { - window.addEventListener('resize', scheduleDecorationRefresh, { passive: true }); + window.addEventListener('resize', handleViewportResize, { passive: true }); window.addEventListener('scroll', scheduleDecorationRefresh, true); document.addEventListener('keydown', handleGlobalKeydown); window.addEventListener('pagehide', restoreVisualOnPageExit); @@ -400,6 +447,20 @@ window.addEventListener('hashchange', restoreVisualAfterSameDocumentNavigation); } + function handleViewportResize() { + scheduleDecorationRefresh(); + if (!feedbackPanel?.classList.contains('visible')) { + return; + } + window.requestAnimationFrame(() => { + if (panelCollapsed) { + anchorPanelToViewportEdge(panelAnchor); + } else { + clampPanelToViewport(); + } + }); + } + function handleGlobalKeydown(event) { if (event.key === 'Escape' && captureModal.classList.contains('visible')) { event.preventDefault(); @@ -489,6 +550,15 @@ } renderVisualInspector(); scheduleDecorationRefresh(); + if (nextMode !== INTERACTION_MODES.OFF) { + window.requestAnimationFrame(() => { + if (panelCollapsed) { + anchorPanelToViewportEdge(panelAnchor); + } else { + clampPanelToViewport(); + } + }); + } return true; } @@ -1817,8 +1887,21 @@ const maxX = Math.max(8, window.innerWidth - feedbackPanel.offsetWidth - 8); const maxY = Math.max(8, window.innerHeight - feedbackPanel.offsetHeight - 8); - const x = clamp(event.clientX - dragOffset.x, 8, maxX); - const y = clamp(event.clientY - dragOffset.y, 8, maxY); + let x = clamp(event.clientX - dragOffset.x, 8, maxX); + let y = clamp(event.clientY - dragOffset.y, 8, maxY); + + if (panelCollapsed) { + const position = getAnchoredPanelPosition( + x, + y, + feedbackPanel.offsetWidth, + feedbackPanel.offsetHeight + ); + panelAnchor = position.edge; + feedbackPanel.dataset.anchor = panelAnchor; + x = position.x; + y = position.y; + } feedbackPanel.style.left = `${x}px`; feedbackPanel.style.top = `${y}px`; @@ -1831,6 +1914,9 @@ feedbackPanel.classList.remove('dragging'); document.removeEventListener('mousemove', handleDragging); document.removeEventListener('mouseup', stopDragging); + if (panelCollapsed) { + anchorPanelToViewportEdge(panelAnchor); + } } function clamp(value, min, max) { diff --git a/docs/chrome-web-store-submission-draft.md b/docs/chrome-web-store-submission-draft.md index f5ecf9e..1acfde4 100644 --- a/docs/chrome-web-store-submission-draft.md +++ b/docs/chrome-web-store-submission-draft.md @@ -1,13 +1,13 @@ # Chrome Web Store Submission Record -Status: Submitted for Chrome Web Store review on July 19, 2026. The publisher contact email is verified, the data-use certifications are complete, and the review/publication result is pending. +Status: v1.6 was submitted on July 19, 2026 and was public by July 20, 2026. The v1.7 package is a local release candidate and has not been uploaded. -The submitted package is v1.6.0. Store submission does not prove the deferred PDF/export or local MCP runtime gates in `docs/manual-release-checklist.md`; do not describe the release as runtime-verified until those checks pass. +The next package is v1.7.0. The existing Store approval does not prove the deferred PDF/export, Visual Edit, local MCP, or v1.7 compact-panel runtime gates in `docs/manual-release-checklist.md`; do not tag or upload v1.7 until those checks pass. ## Ready inputs - Publisher: `FlyingChanges Code` -- Extension package: `dist/dev-feedback-capture-v1.6.0.zip` +- Candidate extension package: `dist/dev-feedback-capture-v1.7.0.zip` - Store icon: `icon128.png` (`128x128` PNG) - Public product page: `https://monroes.tech/software/dev-feedback-capture/` - Privacy policy: `https://monroes.tech/software/dev-feedback-capture/privacy/` @@ -58,7 +58,7 @@ The publisher reviewed and checked the three Developer Program Policies data-use ## Store screenshot plan -Capture the real v1.6 extension operating on its own public product page. Produce full-bleed `1280x800` PNG files with square corners and no padding. +Capture the real v1.7 extension operating on its own public product page. Produce full-bleed `1280x800` PNG files with square corners and no padding. 1. `01-element-capture.png` - Page: Dev Feedback Capture product page. @@ -82,14 +82,14 @@ Before capture: - Use a clean browser window with no personal account data visible. - Clear old test captures, then create a short coherent demo history. - Confirm saved and exported redact evidence cannot reveal original pixels. -- Confirm every screenshot reflects v1.6 behavior, not an older release. +- Confirm every screenshot reflects v1.7 behavior, including the Browser Code icon and edge-anchored compact list. ## Small promotional tile Create after the final screenshots establish the visual direction. - Exact output: `440x280` PNG. -- Use the speech-bubble/cursor icon from `icon128.png` on the purple brand field. +- Use the Browser Code icon from `icon128.png` on the indigo brand field. - Add only the product name and the short line `Visual feedback, ready to build.` - Do not use a raw screenshot, Store badge, ranking claim, or excessive text. @@ -130,12 +130,13 @@ Target: 75-90 seconds, `1920x1080`, recorded in a clean Edge window on the publi - Publisher: `FlyingChanges Code`; durable owner and verified public contact: `monroe@flyingchangesfarm.net`. - Store item ID: `hhdmfaaplpiokafjieefpgoppckijafc`. -- Submitted package: `dist/dev-feedback-capture-v1.6.0.zip`. +- Current public package: v1.6.0. +- Next candidate package: `dist/dev-feedback-capture-v1.7.0.zip` (not uploaded). - Category: Developer Tools; language: English (United States). - The single purpose, permission justifications, no-remote-code declaration, data-use categories, privacy-policy URL, homepage, and support URL were saved before submission. -- One valid 1280x800 screenshot was submitted. Replace it with the fresh v1.6 set above in a later listing update after the current review resolves; avoid changing the active submission unless a reviewer requests it. +- One valid 1280x800 screenshot was submitted with v1.6. Replace it with the fresh v1.7 set above when the v1.7 release gates pass. - Monitor the verified contact email and dashboard for approval or a focused reviewer request. - Confirm the dashboard's publication timing choice before an approved item goes live; that setting was not independently recorded here. -- Complete the deferred PDF/export and v1.6 MCP manual gates before calling the Store release runtime-verified. +- Complete every open gate in `docs/manual-release-checklist.md` before tagging or uploading v1.7. - The feature video, 440x280 promotional tile, and backup publisher Admin remain optional follow-up work. -- Keep payments, authentication, network sync, and additional permissions out of this v1.6 submission. +- Keep payments, authentication, network sync, and additional permissions out of v1.7. diff --git a/docs/icon-options.html b/docs/icon-options.html new file mode 100644 index 0000000..89f2da4 --- /dev/null +++ b/docs/icon-options.html @@ -0,0 +1,485 @@ + + + + + + Dev Feedback Capture — HTML Icon Directions + + + + + +
+
+
+

Dev Feedback Capture · Icon direction

+

Which one says “HTML tool”?

+

No shields, chat bubbles, or security language. Each direction is shown large and at the actual 16 px toolbar size. Pick the shape first; color and fine detail can be tuned afterward.

+
+
+ Your selection + Nothing selected yet +
+
+ +
+
+ 01 +
+ +
+
+

HTML File

+

A literal document plus markup. The most explicit “this works with HTML files” direction.

+
+
16 px toolbar
+ +
+ +
+ 02 + Recommended +
+ +
+
+

Browser Code

+

Browser chrome plus orange markup. Reads as a web-development extension before anything else.

+
+
16 px toolbar
+ +
+ +
+ 03 +
+ +
+
+

Tag Monogram

+

A compact <H> mark. Loudest HTML signal and the strongest silhouette at tiny sizes.

+
+
16 px toolbar
+ +
+ +
+ 04 +
+ +
+
+

Inspect Frame

+

Markup inside a selection frame. Connects HTML with the extension’s element-capture workflow.

+
+
16 px toolbar
+ +
+ +
+ 05 +
+ +
+
+

DOM Tree

+

HTML structure rather than a file. More technical and distinctive, with a clear hierarchy signal.

+
+
16 px toolbar
+ +
+ +
+ 06 +
+ +
+
+

Markup Layers

+

Code on stacked page evidence. Connects HTML with capture, context, and implementation handoff.

+
+
16 px toolbar
+ +
+
+ +
+ 02 Browser Code selected. Local next-version assets now use this direction. + The published Store v1.6 icon remains unchanged until the next reviewed package is uploaded. +
+
+ + + + diff --git a/docs/manual-release-checklist.md b/docs/manual-release-checklist.md index 3ea1f2f..63836e1 100644 --- a/docs/manual-release-checklist.md +++ b/docs/manual-release-checklist.md @@ -2,7 +2,17 @@ Automated checks are necessary but do not replace the unpacked-extension gate. -Store status on July 19, 2026: the v1.6 package was submitted for Chrome Web Store review before the deferred manual gates below were completed. Store approval is not proof that these checks passed. Keep them open and do not call the release runtime-verified until the relevant evidence is recorded. +Store status on July 25, 2026: v1.6 is public in the Chrome Web Store. Store approval is not proof that the deferred checks below passed. Keep them open and do not tag, upload, or call v1.7 runtime-verified until the relevant evidence is recorded. + +## v1.7 compact-panel and icon check + +Before tagging or uploading v1.7: + +- Reload the unpacked extension from this exact repository checkout. +- In Element and Visual modes, drag the collapsed change list near every viewport edge and confirm it stays anchored to the nearest edge. +- Resize the browser window and confirm the collapsed list remains visible on its selected edge. +- Confirm **⌃** expands the list, **⌄** collapses it, and both controls have matching accessible labels. +- Confirm the Browser Code icon is legible in the browser toolbar and extension-management list at the packaged sizes. ## Deferred v1.4 PDF/export check diff --git a/docs/v1.7-product-plan.html b/docs/v1.7-product-plan.html new file mode 100644 index 0000000..56bf639 --- /dev/null +++ b/docs/v1.7-product-plan.html @@ -0,0 +1,461 @@ + + + + + + Dev Feedback Capture v1.7 Product Plan + + + +
+
+
Dev Feedback Capture · July 25, 2026
+

Make v1.7 obvious before making it paid

+

The strongest next release is a trust-and-activation pass: finish the Browser Code identity, make the first successful capture effortless, prove every existing workflow, and tell that story clearly in the Store.

+
+ Local-first + Manifest V3 + No accounts + No telemetry + Explicit export +
+
+ +
+

Executive Summary

+
+
+ Ship v1.7 free. +

There is not enough demand evidence yet to justify accounts, billing, licensing, and the support burden that follows.

+
+
+ Sell the workflow later. +

The paid value is not “take a screenshot.” It is a reliable project inbox, agent handoff, status loop, and team collaboration.

+
+
+ Win on trust now. +

Local storage, minimal permissions, and explicit exports are a real differentiator—especially under Chrome’s stricter 2026 data-disclosure rules.

+
+
+
+ +
+
Decision
+

Best path: one tight free release, then a paid validation offer

+

v1.7 should improve comprehension and close proof gaps, not add a cloud backend. The Browser Code icon and edge-anchored compact panel are already implemented locally. Finish the current manual gates, add a short first-run path, tighten the handoff, and refresh the Store listing.

+

Counterpoint: delaying payment delays revenue. The larger risk is charging before the extension has repeat users or a clear paid boundary; that creates billing complexity without proving anyone wants the product.

+
+ +
+

v1.7 priority score

+ +

Product-judgment score, not measured usage data. It combines user value, confidence, effort, privacy risk, and fit with the current local-first promise.

+
+ +
+

What goes into the next push

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
WhenChangeWhy it earns the slot
NowBrowser Code icon plus the edge-anchored compact list and ⌃ / ⌄ controls.The product reads as a web-development tool and the smallest persistent UI is easier to understand.
NowComplete the three deferred runtime gates: PDF/export/redaction, Visual Edit restoration, and a real MCP handoff.Existing capability is more valuable than another unverified feature. These are release gates, not polish.
NowFirst-run walkthrough: choose Element, Visual, or Region; capture one sample; open History; export.The first win should take under a minute without reading the README.
NowOne named handoff action: “Download for agent,” followed by the exact local import instruction.Users should not need to understand AI Bundle vs JSON for MCP before they get value.
NowTruth cleanup: published version, changelog status, README download language, product metadata, support URL, and privacy text.The repository currently describes v1.6 as in development even though v1.6 is public.
NextAcceptance-check verification with pass/fail and a short implementation note.This closes the feedback loop and creates a more defensible paid workflow later.
LaterFull-page capture, hosted sharing, accounts, integrations, and telemetry.Each expands scope, privacy disclosures, failure modes, and support before demand is proven.
+
+ +
+

Store listing draft

+
+
Name
+

Dev Feedback Capture

+
+
+
Short description
+

Capture element, region, and visual-edit feedback as implementation-ready specs—saved locally and exported only when you choose.

+
+
+
Opening description
+
+

Turn what you see in the browser into a change spec a developer or coding agent can act on.

+

Capture a DOM element, annotate a visible region or PDF, or preview a visual edit. Dev Feedback Capture keeps the selector, screenshot evidence, requested change, page context, and acceptance checks together.

+

Your captures stay in local extension storage. Nothing is uploaded, synced, or sent to an AI service unless you explicitly export it and choose where to send it.

+
+
+
+
Key bullets
+
+

• Element mode — capture selectors, text, styles, and notes
+ • Visual mode — preview reversible layout, text, and style changes
+ • Region mode — annotate pages and PDFs with crops, pins, arrows, text, and redaction
+ • History — review, edit, and export saved feedback
+ • Agent-ready exports — JSON, HTML, Markdown, and an evidence bundle
+ • Local-first — minimal permissions, no always-on page access, no telemetry, no cloud sync

+
+
+
+ +
+

Four screenshots should tell the whole story

+
+
+
01
+

Pick the exact element

+

Show Element mode with the edge-anchored compact list and one clearly highlighted target.

+
+
+
02
+

Mark the visual change

+

Show Region mode with crop, arrow, numbered pin, requested change, and one acceptance check.

+
+
+
03
+

Preview without changing source

+

Show Visual mode with original versus proposed state and the restoration promise.

+
+
+
04
+

Hand it off with context

+

Show History and the one-click agent export, with evidence and structured requirements visible.

+
+
+

Do not lead with MCP terminology. Lead with the job: “capture a change, keep its context, hand it off.”

+
+ +
+

How this can make money

+
+ +
+
After team demand
+

Hosted Team

+
$12–20 / creator / month
+
    +
  • Shared projects and guest links
  • +
  • Assignments, comments, and audit history
  • +
  • GitHub, Linear, Jira, or Slack handoff
  • +
  • Admin and retention controls
  • +
+

Risk: backend security, privacy, billing, support, and integration maintenance become the product.

+
+
+
Do not do
+

Paid basic capture

+
Not yet
+
    +
  • No paywall on Element or Region capture
  • +
  • No ads in the page overlay
  • +
  • No sale of browsing or page data
  • +
  • No cloud account merely to export
  • +
+

Why: it weakens acquisition and trust before the product has demonstrated repeat use.

+
+
+

Comparable products charge for collaboration and workflow depth: Jam lists a free tier and a $14-per-creator Team tier; BugHerd’s Standard plan is $50/month for five members; Marker.io starts at $39/month. That is the signal: capture earns attention, workflow earns money.

+
+ +
+

Validation gate before building billing

+
    +
  1. Recruit five real users—freelance developers, agency owners, QA, or PMs—and watch each complete one capture and export.
  2. +
  3. Get ten people to use it on two separate days within a two-week window. Measure manually or through Store analytics; do not add extension telemetry for this test.
  4. +
  5. Ask for the sale: offer a $49 founding Local Pro license with the promised workflow above. Build it only after at least three people commit to paying.
  6. +
  7. Use one success definition: a user captures a change, hands it to a developer/agent, and records whether the acceptance checks passed.
  8. +
+
Guardrails: permissions remain storage, activeTab, and scripting; no page content leaves the device without an explicit export; no evidence is lost; and every Store privacy disclosure matches actual behavior.
+
+ +
+

Further questions

+
    +
  • Who is the first paying customer: solo developer, agency, QA team, or product manager?
  • +
  • Is the highest-value loop “feedback to agent,” “client to agency,” or “QA to developer”?
  • +
  • Will Local Pro be a separate desktop companion, a supported MCP package, or both?
  • +
  • Which single integration would three paying users choose first?
  • +
+
+ +
+

Caveats and assumptions

+

This plan uses the current source tree, the public v1.6 listing, official Chrome policy, and current competitor pricing. The priority scores and proposed prices are decision aids—not observed conversion data. Before setting a final price, check the Developer Dashboard’s actual listing impressions, installs, and retention signals.

+

Chrome’s updated user-data policy takes effect August 1, 2026. Any future telemetry, accounts, cloud sync, or paid service must be both necessary to the disclosed purpose and prominently disclosed. Chrome’s developer agreement also states that Google is not responsible for processing product payments, authentication of paid downloads, payment records, or taxes.

+
+ +
+

Sources

+ +
+
+ + diff --git a/generate-icons.html b/generate-icons.html index 835c701..fb10f32 100644 --- a/generate-icons.html +++ b/generate-icons.html @@ -13,7 +13,7 @@ text-align: center; } h1 { - color: #667eea; + color: #4338ca; } .icons { display: flex; @@ -31,7 +31,7 @@ margin: 10px auto; } button { - background: #667eea; + background: #4338ca; color: white; border: none; padding: 12px 24px; @@ -42,7 +42,7 @@ margin: 5px; } button:hover { - background: #5568d3; + background: #f05a28; } .instructions { background: #f5f5f5; @@ -53,7 +53,7 @@ } .instructions h3 { margin-top: 0; - color: #667eea; + color: #4338ca; } .instructions ol { line-height: 1.8; @@ -110,64 +110,51 @@

Instructions:

const canvas = document.getElementById(canvasId); const ctx = canvas.getContext('2d'); - // Background gradient - const gradient = ctx.createLinearGradient(0, 0, size, size); - gradient.addColorStop(0, '#667eea'); - gradient.addColorStop(1, '#764ba2'); - ctx.fillStyle = gradient; - ctx.fillRect(0, 0, size, size); - - // Draw feedback icon (speech bubble with cursor) - ctx.fillStyle = 'white'; - - // Scale everything based on size const scale = size / 128; - // Speech bubble - const bubbleX = size * 0.25; - const bubbleY = size * 0.2; - const bubbleWidth = size * 0.55; - const bubbleHeight = size * 0.45; - const radius = size * 0.08; + // Indigo extension tile. + ctx.fillStyle = '#4338ca'; + ctx.beginPath(); + ctx.roundRect(3 * scale, 3 * scale, 122 * scale, 122 * scale, 27 * scale); + ctx.fill(); - // Draw rounded rectangle (speech bubble) + // White browser window. + ctx.fillStyle = '#fff'; ctx.beginPath(); - ctx.moveTo(bubbleX + radius, bubbleY); - ctx.lineTo(bubbleX + bubbleWidth - radius, bubbleY); - ctx.quadraticCurveTo(bubbleX + bubbleWidth, bubbleY, bubbleX + bubbleWidth, bubbleY + radius); - ctx.lineTo(bubbleX + bubbleWidth, bubbleY + bubbleHeight - radius); - ctx.quadraticCurveTo(bubbleX + bubbleWidth, bubbleY + bubbleHeight, bubbleX + bubbleWidth - radius, bubbleY + bubbleHeight); + ctx.roundRect(20 * scale, 26 * scale, 88 * scale, 76 * scale, 12 * scale); + ctx.fill(); - // Tail of speech bubble - ctx.lineTo(bubbleX + bubbleWidth * 0.4, bubbleY + bubbleHeight); - ctx.lineTo(bubbleX + bubbleWidth * 0.3, bubbleY + bubbleHeight + size * 0.15); - ctx.lineTo(bubbleX + bubbleWidth * 0.3, bubbleY + bubbleHeight); + ctx.strokeStyle = '#dfe1ee'; + ctx.lineWidth = 6 * scale; + ctx.beginPath(); + ctx.moveTo(20 * scale, 41 * scale); + ctx.lineTo(108 * scale, 41 * scale); + ctx.stroke(); - ctx.lineTo(bubbleX + radius, bubbleY + bubbleHeight); - ctx.quadraticCurveTo(bubbleX, bubbleY + bubbleHeight, bubbleX, bubbleY + bubbleHeight - radius); - ctx.lineTo(bubbleX, bubbleY + radius); - ctx.quadraticCurveTo(bubbleX, bubbleY, bubbleX + radius, bubbleY); - ctx.closePath(); + ctx.fillStyle = '#f05a28'; + ctx.beginPath(); + ctx.arc(31 * scale, 34 * scale, 3 * scale, 0, Math.PI * 2); + ctx.fill(); + ctx.fillStyle = '#f5b942'; + ctx.beginPath(); + ctx.arc(41 * scale, 34 * scale, 3 * scale, 0, Math.PI * 2); ctx.fill(); - // Add cursor icon in the bubble - if (size >= 48) { - ctx.fillStyle = '#667eea'; - const cursorSize = size * 0.15; - const cursorX = bubbleX + bubbleWidth * 0.3; - const cursorY = bubbleY + bubbleHeight * 0.35; - - // Draw cursor arrow - ctx.beginPath(); - ctx.moveTo(cursorX, cursorY); - ctx.lineTo(cursorX, cursorY + cursorSize); - ctx.lineTo(cursorX + cursorSize * 0.4, cursorY + cursorSize * 0.7); - ctx.lineTo(cursorX + cursorSize * 0.6, cursorY + cursorSize); - ctx.lineTo(cursorX + cursorSize * 0.5, cursorY + cursorSize * 0.6); - ctx.lineTo(cursorX + cursorSize, cursorY + cursorSize * 0.5); - ctx.closePath(); - ctx.fill(); - } + // Orange markup mark. + ctx.strokeStyle = '#f05a28'; + ctx.lineWidth = 7 * scale; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.beginPath(); + ctx.moveTo(53 * scale, 57 * scale); + ctx.lineTo(41 * scale, 68 * scale); + ctx.lineTo(53 * scale, 79 * scale); + ctx.moveTo(75 * scale, 57 * scale); + ctx.lineTo(87 * scale, 68 * scale); + ctx.lineTo(75 * scale, 79 * scale); + ctx.moveTo(68 * scale, 52 * scale); + ctx.lineTo(59 * scale, 84 * scale); + ctx.stroke(); } // Download a single icon diff --git a/icon-source.svg b/icon-source.svg new file mode 100644 index 0000000..1dc031d --- /dev/null +++ b/icon-source.svg @@ -0,0 +1,17 @@ + + Dev Feedback Capture browser code icon + An orange code symbol inside a white browser window on an indigo rounded square. + + + + + + + diff --git a/icon128.png b/icon128.png index 0c3d3675b5c93b65fedd7f4a14d32aa154fab418..808ef3ddd32808af86ee696174749b961bbafc00 100644 GIT binary patch delta 2804 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 HAt?3#rk!pY diff --git a/icon16.png b/icon16.png index a6a8919d86c3e61f6f57901a226e7916a001a75b..2ba902ab9fb81a09c953df4573f1e39bfa58f696 100644 GIT binary patch delta 412 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 IM6N<$g19h5UH||9 diff --git a/manifest.json b/manifest.json index 726f617..3131fe1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 3, "name": "Dev Feedback Capture", - "version": "1.6.0", - "description": "Capture visual change specs and hand them to a project-scoped local MCP agent", + "version": "1.7.0", + "description": "Capture element, region, and visual-edit feedback as implementation-ready specs, saved locally until you export.", "permissions": [ "storage", "activeTab", diff --git a/mcp/server.mjs b/mcp/server.mjs index f0e06f3..fbd20c2 100644 --- a/mcp/server.mjs +++ b/mcp/server.mjs @@ -14,7 +14,7 @@ export async function createDevFeedbackServer(options = {}) { const readOnly = Boolean(options.readOnly); const server = new McpServer({ name: 'dev-feedback-capture', - version: options.version || '1.6.0', + version: options.version || '1.7.0', description: 'Project-scoped local feedback and evidence for coding agents.' }); diff --git a/package-lock.json b/package-lock.json index 0b36efc..a917224 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dev-feedback-capture", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dev-feedback-capture", - "version": "1.6.0", + "version": "1.7.0", "license": "UNLICENSED", "dependencies": { "@modelcontextprotocol/sdk": "1.29.0", diff --git a/package.json b/package.json index 2a60aa0..d62222a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "dev-feedback-capture", "private": true, - "version": "1.6.0", + "version": "1.7.0", "license": "UNLICENSED", "description": "Chrome extension for capturing structured feedback on web pages and PDFs", "scripts": { diff --git a/product.json b/product.json index 4e14435..adddbaa 100644 --- a/product.json +++ b/product.json @@ -3,9 +3,9 @@ "name": "Dev Feedback Capture", "kind": "browser-extension", "summary": "Local-first Chromium extension and project-scoped MCP companion for actionable visual change specs.", - "status": "preview", + "status": "public", "repo": "https://github.com/StoneHub/webDevFeedbackExt", - "liveUrl": "", + "liveUrl": "https://chromewebstore.google.com/detail/dev-feedback-capture/hhdmfaaplpiokafjieefpgoppckijafc", "releaseUrl": "https://github.com/StoneHub/webDevFeedbackExt/releases", "downloadUrl": "https://github.com/StoneHub/webDevFeedbackExt/releases/download/v1.2.0/dev-feedback-capture-v1.2.0.zip", "supportUrl": "mailto:monroe@flyingchangesfarm.net", @@ -26,8 +26,8 @@ "summary": "Feedback stays in local extension storage or an explicitly selected project sidecar. Capture, export, and MCP import actions are user-triggered, and no cloud sync or hosted AI integration is included." }, "distribution": { - "current": "Versioned zip assets are published through GitHub Releases for manual unpacked installation.", - "planned": "Keep the catalog download link aligned with the latest published release.", + "current": "Chrome Web Store v1.6 is public. GitHub Release v1.2.0 remains available for manual unpacked installation.", + "planned": "Publish v1.7 only after the recorded browser and agent-handoff release gates pass, then align the catalog download link.", "latestReleaseApi": "https://api.github.com/repos/StoneHub/webDevFeedbackExt/releases/latest", "assetNamePattern": "dev-feedback-capture-v{version}.zip", "downloadUrlPolicy": "Resolve the latest release asset at publish time instead of hardcoding a stale versioned URL." diff --git a/scripts/generate-icons.ps1 b/scripts/generate-icons.ps1 index a6e0a6f..b9560f1 100644 --- a/scripts/generate-icons.ps1 +++ b/scripts/generate-icons.ps1 @@ -2,18 +2,6 @@ Add-Type -AssemblyName System.Drawing $root = Split-Path -Parent $PSScriptRoot -function New-Brush([int]$size) { - $start = [System.Drawing.Point]::new(0, 0) - $end = [System.Drawing.Point]::new($size, $size) - $brush = [System.Drawing.Drawing2D.LinearGradientBrush]::new( - $start, - $end, - [System.Drawing.ColorTranslator]::FromHtml('#667eea'), - [System.Drawing.ColorTranslator]::FromHtml('#764ba2') - ) - return $brush -} - function Draw-RoundedRectangle { param( [System.Drawing.Graphics]$Graphics, @@ -44,49 +32,42 @@ function Draw-Icon([int]$size, [string]$path) { $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias $graphics.Clear([System.Drawing.Color]::Transparent) - $backgroundBrush = New-Brush $size - $graphics.FillRectangle($backgroundBrush, 0, 0, $size, $size) - + $scale = $size / 128.0 + $backgroundBrush = [System.Drawing.SolidBrush]::new([System.Drawing.ColorTranslator]::FromHtml('#4338ca')) $whiteBrush = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::White) - $accentBrush = [System.Drawing.SolidBrush]::new([System.Drawing.ColorTranslator]::FromHtml('#667eea')) - - $bubbleX = $size * 0.22 - $bubbleY = $size * 0.18 - $bubbleWidth = $size * 0.58 - $bubbleHeight = $size * 0.44 - $radius = [Math]::Max(2, $size * 0.08) - - Draw-RoundedRectangle -Graphics $graphics -Brush $whiteBrush -X $bubbleX -Y $bubbleY -Width $bubbleWidth -Height $bubbleHeight -Radius $radius - - $tail = [System.Drawing.Drawing2D.GraphicsPath]::new() - $tail.StartFigure() - $tail.AddLine($bubbleX + ($bubbleWidth * 0.46), $bubbleY + $bubbleHeight, $bubbleX + ($bubbleWidth * 0.34), $bubbleY + $bubbleHeight + ($size * 0.15)) - $tail.AddLine($bubbleX + ($bubbleWidth * 0.34), $bubbleY + $bubbleHeight + ($size * 0.15), $bubbleX + ($bubbleWidth * 0.34), $bubbleY + $bubbleHeight) - $tail.CloseFigure() - $graphics.FillPath($whiteBrush, $tail) - $tail.Dispose() - - if ($size -ge 48) { - $cursor = [System.Drawing.Drawing2D.GraphicsPath]::new() - $cursorX = $bubbleX + ($bubbleWidth * 0.32) - $cursorY = $bubbleY + ($bubbleHeight * 0.28) - $cursorSize = $size * 0.18 - - $cursor.StartFigure() - $cursor.AddLine($cursorX, $cursorY, $cursorX, $cursorY + $cursorSize) - $cursor.AddLine($cursorX, $cursorY + $cursorSize, $cursorX + ($cursorSize * 0.38), $cursorY + ($cursorSize * 0.68)) - $cursor.AddLine($cursorX + ($cursorSize * 0.38), $cursorY + ($cursorSize * 0.68), $cursorX + ($cursorSize * 0.55), $cursorY + $cursorSize) - $cursor.AddLine($cursorX + ($cursorSize * 0.55), $cursorY + $cursorSize, $cursorX + ($cursorSize * 0.47), $cursorY + ($cursorSize * 0.58)) - $cursor.AddLine($cursorX + ($cursorSize * 0.47), $cursorY + ($cursorSize * 0.58), $cursorX + $cursorSize, $cursorY + ($cursorSize * 0.5)) - $cursor.CloseFigure() - - $graphics.FillPath($accentBrush, $cursor) - $cursor.Dispose() - } + $orangeBrush = [System.Drawing.SolidBrush]::new([System.Drawing.ColorTranslator]::FromHtml('#f05a28')) + $yellowBrush = [System.Drawing.SolidBrush]::new([System.Drawing.ColorTranslator]::FromHtml('#f5b942')) + + Draw-RoundedRectangle -Graphics $graphics -Brush $backgroundBrush -X (3 * $scale) -Y (3 * $scale) -Width (122 * $scale) -Height (122 * $scale) -Radius (27 * $scale) + Draw-RoundedRectangle -Graphics $graphics -Brush $whiteBrush -X (20 * $scale) -Y (26 * $scale) -Width (88 * $scale) -Height (76 * $scale) -Radius (12 * $scale) + + $dividerPen = [System.Drawing.Pen]::new([System.Drawing.ColorTranslator]::FromHtml('#dfe1ee'), 6 * $scale) + $graphics.DrawLine($dividerPen, 20 * $scale, 41 * $scale, 108 * $scale, 41 * $scale) + $graphics.FillEllipse($orangeBrush, 28 * $scale, 31 * $scale, 6 * $scale, 6 * $scale) + $graphics.FillEllipse($yellowBrush, 38 * $scale, 31 * $scale, 6 * $scale, 6 * $scale) + + $codePen = [System.Drawing.Pen]::new([System.Drawing.ColorTranslator]::FromHtml('#f05a28'), 7 * $scale) + $codePen.StartCap = [System.Drawing.Drawing2D.LineCap]::Round + $codePen.EndCap = [System.Drawing.Drawing2D.LineCap]::Round + $codePen.LineJoin = [System.Drawing.Drawing2D.LineJoin]::Round + $graphics.DrawLines($codePen, [System.Drawing.PointF[]]@( + [System.Drawing.PointF]::new(53 * $scale, 57 * $scale), + [System.Drawing.PointF]::new(41 * $scale, 68 * $scale), + [System.Drawing.PointF]::new(53 * $scale, 79 * $scale) + )) + $graphics.DrawLines($codePen, [System.Drawing.PointF[]]@( + [System.Drawing.PointF]::new(75 * $scale, 57 * $scale), + [System.Drawing.PointF]::new(87 * $scale, 68 * $scale), + [System.Drawing.PointF]::new(75 * $scale, 79 * $scale) + )) + $graphics.DrawLine($codePen, 68 * $scale, 52 * $scale, 59 * $scale, 84 * $scale) $bitmap.Save($path, [System.Drawing.Imaging.ImageFormat]::Png) - $accentBrush.Dispose() + $codePen.Dispose() + $dividerPen.Dispose() + $yellowBrush.Dispose() + $orangeBrush.Dispose() $whiteBrush.Dispose() $backgroundBrush.Dispose() $graphics.Dispose() diff --git a/styles.css b/styles.css index d1977a5..004fca0 100644 --- a/styles.css +++ b/styles.css @@ -160,6 +160,12 @@ font: 700 13px/1 Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } +.dev-feedback-panel-toggle { + font-size: 19px; + line-height: 0.8; + padding-bottom: 3px; +} + .dev-feedback-panel-toggle:hover, .dev-feedback-panel-close:hover { background: var(--df-surface-high); @@ -169,6 +175,11 @@ #dev-feedback-panel.collapsed { width: auto; max-height: none; + transition: left 120ms ease, top 120ms ease; +} + +#dev-feedback-panel.collapsed.dragging { + transition: none; } #dev-feedback-panel.collapsed .dev-feedback-panel-header { diff --git a/test/mcp.test.mjs b/test/mcp.test.mjs index 2aee5dc..a0a71fa 100644 --- a/test/mcp.test.mjs +++ b/test/mcp.test.mjs @@ -225,7 +225,7 @@ test('History JSON import is idempotent and strips embedded evidence', async (t) test('MCP protocol exposes project-scoped tools and resources', async (t) => { const fixture = await createFixture(t); - const { server } = await createDevFeedbackServer({ projectRoot: fixture.projectRoot, inboxRoots: [fixture.inboxRoot], version: '1.6.0-test' }); + const { server } = await createDevFeedbackServer({ projectRoot: fixture.projectRoot, inboxRoots: [fixture.inboxRoot], version: '1.7.0-test' }); const client = new Client({ name: 'mcp-test-client', version: '1.0.0' }, { capabilities: {} }); const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]); @@ -505,7 +505,7 @@ test('CLI speaks clean MCP over stdio', async (t) => { const tools = await client.listTools(); assert.equal(tools.tools.some((tool) => tool.name === 'dev_feedback_list'), true); await new Promise((resolve) => setTimeout(resolve, 20)); - assert.match(diagnostics, /Dev Feedback MCP 1\.6\.0 connected/); + assert.match(diagnostics, /Dev Feedback MCP 1\.7\.0 connected/); }); async function createFixture(t) { diff --git a/test/release.test.cjs b/test/release.test.cjs index 5a6e965..d113233 100644 --- a/test/release.test.cjs +++ b/test/release.test.cjs @@ -652,6 +652,11 @@ assert.match(historySource, /function redactEvidenceRect/); assert.match(historySource, /annotatedImages\.get\(item\.id\)/); assert.match(contentSource, /classList\.add\('collapsed'\)/); assert.match(contentSource, /aria-expanded="false"/); +assert.match(contentSource, /title="Expand changes"[\s\S]*>⌃<\/button>/); +assert.match(contentSource, /button\.textContent = panelCollapsed \? '⌃' : '⌄'/); +assert.match(contentSource, /function getAnchoredPanelPosition\(/); +assert.match(contentSource, /function anchorPanelToViewportEdge\(/); +assert.match(contentSource, /if \(panelCollapsed\) \{[\s\S]*anchorPanelToViewportEdge\(panelAnchor\);/); assert.match(backgroundSource, /files: \['shared\.js', 'visual-edit\.js', 'content\.js'\]/); assert.match(contentSource, /function cancelVisualEdit\(\) \{[\s\S]*if \(visualBusy\)[\s\S]*restoreVisualSession\(\);/); assert.match(contentSource, /function stopInteractionMode\(\) \{\s*setInteractionMode\(INTERACTION_MODES\.OFF, \{ discardVisual: true \}\);/); From 0b36efdb492fe6da849e56c429adac7d5b3f1068 Mon Sep 17 00:00:00 2001 From: StoneHub Date: Sat, 25 Jul 2026 11:32:46 -0400 Subject: [PATCH 2/3] Soften v1.7 palette and expand by default --- CHANGELOG.md | 1 + QUICKSTART.md | 2 +- capture.html | 79 +++++++++-------- content.js | 7 +- docs/manual-release-checklist.md | 1 + history.css | 34 +++---- popup.html | 80 +++++++++-------- styles.css | 147 ++++++++++++++++--------------- test/release.test.cjs | 7 +- 9 files changed, 182 insertions(+), 176 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fb6361..54b2857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Replaced the generic speech-bubble icon with the Browser Code mark across packaged 16, 48, and 128 pixel assets. - Anchored the collapsed in-page change list to the nearest viewport edge while preserving drag movement around the viewport perimeter. - Replaced ambiguous plus/minus controls with explicit up/down chevrons and clearer accessible labels. +- Opened the in-page change list by default and replaced the terminal-green theme with a softer paper-and-indigo palette across the popup, page panel, capture editor, and history. - Added the v1.7 product, Store-listing, and monetization plan plus reusable icon-choice source assets. ## 1.6.0 (Published July 20, 2026) diff --git a/QUICKSTART.md b/QUICKSTART.md index 5762bea..22e932b 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -25,7 +25,7 @@ Optional for local PDFs: 3. Leave the mode on `Element`. 4. Click `Start Element Mode` or press `Ctrl+Shift+F` (`Command+Shift+F` on macOS). 5. Click a page element, add your note, and save it. -6. The in-page capture list starts collapsed and stays on the nearest viewport edge as you drag it. Use **⌃** to expand it and **⌄** to collapse it again. +6. The in-page capture list starts expanded. Use **⌄** to collapse it; the compact list stays on the nearest viewport edge as you drag it, and **⌃** expands it again. ## 3. Preview a visual edit diff --git a/capture.html b/capture.html index b2f2cc4..6aa4403 100644 --- a/capture.html +++ b/capture.html @@ -6,18 +6,18 @@ Visual Change Spec