From 93eca93bf3f374e572d6054e0a25a8a8d5d5a06c Mon Sep 17 00:00:00 2001 From: hashfunction Date: Sun, 30 Aug 2026 20:12:43 -0700 Subject: [PATCH 1/2] release: prepare 3.1.1 --- CHANGELOG.md | 11 ++++++++++ README.md | 4 ++-- app-store/metadata/en-US.md | 4 ++-- app-store/review-notes.md | 10 +++++++--- electron-builder.mas.yml | 2 +- package-lock.json | 4 ++-- package.json | 2 +- scripts/verify-brand.mjs | 2 +- .../components/settings/CliBridgeSetup.tsx | 2 +- tests/unit/appStoreMetadata.test.ts | 4 +++- tests/unit/brandAudit.test.ts | 2 +- tests/unit/cliBridgeDocumentation.test.ts | 20 +++++++++---------- tests/unit/cliBridgeSetup.test.ts | 2 +- tests/unit/publicPackageVerification.test.ts | 12 +++++------ 14 files changed, 49 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 671df35..01160ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Notarization no longer skips silently: missing credentials, a non-Developer ID certificate, or a failed submission now fail the release build. - Release notes now list the real `markuprplus-*` artifact names and no longer overwrite the curated changelog. +## 3.1.1 - 2026-08-30 + +### Fixed + +- AI-analyzed reports now place each marked screenshot directly inside its matching feedback item, beside the finding's narration and metadata. +- Marked evidence that cannot be matched confidently is preserved in an Unmatched Marked Evidence section instead of being discarded. + +### Changed + +- Bumped the Mac App Store bundle to version 3.1.1, build 4. + ## 3.1.0 - 2026-08-30 ### Added diff --git a/README.md b/README.md index d382102..d032e35 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@

CI status Deployment status - Version 3.1.0 + Version 3.1.1 Platforms Local Whisper transcription License @@ -134,7 +134,7 @@ The sandboxed Mac App Store app can use AI command-line tools already installed Install and pair it from a Terminal: ```bash -npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.0/markuprx-3.1.0.tgz +npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.1/markuprx-3.1.1.tgz markuprx bridge install # installs and starts a per-user LaunchAgent markuprx bridge token # paste this value in Settings → Advanced markuprx bridge status diff --git a/app-store/metadata/en-US.md b/app-store/metadata/en-US.md index 50b2f6c..75214af 100644 --- a/app-store/metadata/en-US.md +++ b/app-store/metadata/en-US.md @@ -12,8 +12,8 @@ Circle the bug. Give your AI the whole story. MarkuprPlus turns each mark and sp ## Keywords bug report,screen recorder,AI feedback,annotation,transcription,Markdown,QA,code review,screenshot -## What's New in Version 3.1.0 -CLI report integrations are back in the Mac App Store app through an optional local companion. Connect Codex CLI, Claude Code CLI, OpenCode, Cursor Agent, Qwen Code, Goose, Amp, Kiro, or Aider from Advanced Settings. This update also adds secure Keychain pairing, bridge status diagnostics, and stricter report-transport limits. Local Rules remains available with no setup or network connection. +## What's New in Version 3.1.1 +Marked screenshots now appear directly inside the matching AI-generated issue, keeping each finding's visual evidence beside its title, narration, and timestamp. Evidence that cannot be matched confidently is preserved in an Unmatched Marked Evidence section. This update also includes the CLI integrations and secure optional local companion introduced in version 3.1.0. ## Description Circle the bug. Give your AI the whole story. diff --git a/app-store/review-notes.md b/app-store/review-notes.md index 252265a..971e55c 100644 --- a/app-store/review-notes.md +++ b/app-store/review-notes.md @@ -1,4 +1,4 @@ -# App Review Notes — MarkuprPlus 3.1.0 +# App Review Notes — MarkuprPlus 3.1.1 MarkuprPlus is a menu bar app for creating structured visual-feedback reports for AI coding agents. It does not require an account and has no developer-operated telemetry. @@ -13,11 +13,15 @@ MarkuprPlus is a menu bar app for creating structured visual-feedback reports fo 7. Press Command-Shift-F again to stop. MarkuprPlus writes a local report and opens the review surface. 8. Edit or reorder findings, preview the Markdown, and export or copy the report path. +## Version 3.1.1 fix + +Marked screenshots are now placed directly inside their matching AI-generated feedback items. When a screenshot cannot be matched confidently, the evidence remains available in an Unmatched Marked Evidence section instead of being discarded. + ## Optional CLI Bridge -Version 3.1.0 restores optional compatibility with Codex CLI, Claude Code CLI, OpenCode, Cursor Agent, Qwen Code, Goose, Amp, Kiro, and Aider. This feature is not required to complete the review walkthrough above. +Version 3.1.1 includes optional compatibility with Codex CLI, Claude Code CLI, OpenCode, Cursor Agent, Qwen Code, Goose, Amp, Kiro, and Aider. This feature is not required to complete the review walkthrough above. -To test it, install the versioned package from the public project release in Terminal with `npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.0/markuprx-3.1.0.tgz`, run `markuprx bridge install`, then run `markuprx bridge token`. In MarkuprPlus, open Settings → Advanced, paste that token into CLI Integrations, and choose any compatible CLI already installed and signed in for the reviewer. `markuprx bridge status` reports whether the per-user companion is running. +To test it, install the versioned package from the public project release in Terminal with `npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.1/markuprx-3.1.1.tgz`, run `markuprx bridge install`, then run `markuprx bridge token`. In MarkuprPlus, open Settings → Advanced, paste that token into CLI Integrations, and choose any compatible CLI already installed and signed in for the reviewer. `markuprx bridge status` reports whether the per-user companion is running. The companion binds only to IPv4 loopback at `127.0.0.1:49647`, requires bearer-token authentication, and accepts only a fixed structured report protocol. The Mac App Store app does not execute external command-line tools inside its sandbox, does not accept or send arbitrary shell commands, and does not install the companion. The separately installed companion invokes only the provider explicitly selected by the user. diff --git a/electron-builder.mas.yml b/electron-builder.mas.yml index f2fab19..860af7d 100644 --- a/electron-builder.mas.yml +++ b/electron-builder.mas.yml @@ -2,7 +2,7 @@ appId: com.eddiesanjuan.markuprx productName: MarkuprPlus executableName: MarkuprPlus copyright: Copyright 2026 Trieflow LLC -buildVersion: "3" +buildVersion: "4" directories: output: release-mas diff --git a/package-lock.json b/package-lock.json index 3794111..5514adf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "markuprx", - "version": "3.1.0", + "version": "3.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "markuprx", - "version": "3.1.0", + "version": "3.1.1", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 3918898..c7ba543 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "markuprx", "productName": "MarkuprPlus", - "version": "3.1.0", + "version": "3.1.1", "description": "Record your screen, narrate feedback, get structured Markdown with screenshots. Desktop app, CLI, and MCP server for AI coding agents like Claude Code, Cursor, and Windsurf.", "type": "module", "main": "dist/main/index.mjs", diff --git a/scripts/verify-brand.mjs b/scripts/verify-brand.mjs index fe51109..c2453b5 100644 --- a/scripts/verify-brand.mjs +++ b/scripts/verify-brand.mjs @@ -85,7 +85,7 @@ export function findBrandViolations(files, readFile, packageJson) { const expectedPackageFields = { name: 'markuprx', productName: 'MarkuprPlus', - version: '3.1.0', + version: '3.1.1', homepage: 'https://markuprplus.com', repository: { type: 'git', diff --git a/src/renderer/components/settings/CliBridgeSetup.tsx b/src/renderer/components/settings/CliBridgeSetup.tsx index b9fa434..15c405b 100644 --- a/src/renderer/components/settings/CliBridgeSetup.tsx +++ b/src/renderer/components/settings/CliBridgeSetup.tsx @@ -5,7 +5,7 @@ import { useTheme } from '../../hooks/useTheme'; import { styles } from './settingsStyles'; export const CLI_BRIDGE_SETUP_COMMANDS = [ - 'npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.0/markuprx-3.1.0.tgz', + 'npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.1/markuprx-3.1.1.tgz', 'markuprx bridge install', 'markuprx bridge token', ] as const; diff --git a/tests/unit/appStoreMetadata.test.ts b/tests/unit/appStoreMetadata.test.ts index f683286..f817fe5 100644 --- a/tests/unit/appStoreMetadata.test.ts +++ b/tests/unit/appStoreMetadata.test.ts @@ -70,6 +70,8 @@ describe('App Store public metadata', () => { expect(fields.description).toMatch(/Codex CLI/); expect(fields.description).toMatch(/optional local companion/i); expect(fields.description).not.toMatch(/App Store app (?:directly )?(?:runs|executes|launches).*CLI/is); - expect(section(metadata, "What's New in Version 3.1.0").length).toBeLessThanOrEqual(4_000); + const releaseNotes = section(metadata, "What's New in Version 3.1.1"); + expect(releaseNotes.length).toBeGreaterThan(0); + expect(releaseNotes.length).toBeLessThanOrEqual(4_000); }); }); diff --git a/tests/unit/brandAudit.test.ts b/tests/unit/brandAudit.test.ts index 3c3cd98..9722c4c 100644 --- a/tests/unit/brandAudit.test.ts +++ b/tests/unit/brandAudit.test.ts @@ -13,7 +13,7 @@ type BrandVerifier = { const compatiblePackageJson = { name: 'markuprx', productName: 'MarkuprPlus', - version: '3.1.0', + version: '3.1.1', homepage: 'https://markuprplus.com', repository: { type: 'git', diff --git a/tests/unit/cliBridgeDocumentation.test.ts b/tests/unit/cliBridgeDocumentation.test.ts index 03f7c00..24b0de0 100644 --- a/tests/unit/cliBridgeDocumentation.test.ts +++ b/tests/unit/cliBridgeDocumentation.test.ts @@ -11,24 +11,24 @@ const lifecycleCommands = [ ]; describe('CLI Bridge release documentation', () => { - it('sets version 3.1.0 and Mac App Store build 3', async () => { + it('sets version 3.1.1 and Mac App Store build 4', async () => { const [packageJson, lockJson, masConfig] = await Promise.all([ readFile('package.json', 'utf8').then(JSON.parse), readFile('package-lock.json', 'utf8').then(JSON.parse), readFile('electron-builder.mas.yml', 'utf8'), ]); - expect(packageJson.version).toBe('3.1.0'); - expect(lockJson.version).toBe('3.1.0'); - expect(lockJson.packages[''].version).toBe('3.1.0'); - expect(masConfig).toMatch(/^buildVersion: "3"$/m); + expect(packageJson.version).toBe('3.1.1'); + expect(lockJson.version).toBe('3.1.1'); + expect(lockJson.packages[''].version).toBe('3.1.1'); + expect(masConfig).toMatch(/^buildVersion: "4"$/m); }); it('documents the complete optional companion lifecycle and fixed loopback endpoint', async () => { const readme = await readFile('README.md', 'utf8'); expect(readme).toMatch(/optional.*companion/is); expect(readme).toContain( - 'npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.0/markuprx-3.1.0.tgz', + 'npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.1/markuprx-3.1.1.tgz', ); for (const command of lifecycleCommands) expect(readme).toContain(command); expect(readme).toContain('127.0.0.1:49647'); @@ -48,14 +48,14 @@ describe('CLI Bridge release documentation', () => { expect(content).toMatch(/companion/i); expect(content).toMatch(/(?:localhost|loopback|127\.0\.0\.1)/i); } - expect(metadata).toContain("## What's New in Version 3.1.0"); - expect(reviewNotes).toContain('# App Review Notes — MarkuprPlus 3.1.0'); + expect(metadata).toContain("## What's New in Version 3.1.1"); + expect(reviewNotes).toContain('# App Review Notes — MarkuprPlus 3.1.1'); expect(reviewNotes).toContain( - 'https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.0/markuprx-3.1.0.tgz', + 'https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.1/markuprx-3.1.1.tgz', ); expect(reviewNotes.indexOf('Local Rules')).toBeLessThan(reviewNotes.indexOf('Optional CLI Bridge')); expect(reviewNotes).toMatch(/does not execute external.*inside.*sandbox/is); expect(privacyPage).toMatch(/transcript.*selected screenshots.*companion/is); - expect(changelog).toMatch(/^## 3\.1\.0 - 2026-08-30$/m); + expect(changelog).toMatch(/^## 3\.1\.1 - 2026-08-30$/m); }); }); diff --git a/tests/unit/cliBridgeSetup.test.ts b/tests/unit/cliBridgeSetup.test.ts index bd6e366..7a2e413 100644 --- a/tests/unit/cliBridgeSetup.test.ts +++ b/tests/unit/cliBridgeSetup.test.ts @@ -7,7 +7,7 @@ import { describe('CLI bridge setup presentation', () => { it('provides deterministic install, start, and token commands', () => { expect(CLI_BRIDGE_SETUP_COMMANDS).toEqual([ - 'npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.0/markuprx-3.1.0.tgz', + 'npm install -g https://github.com/hashfunction/MarkuprPlus/releases/download/v3.1.1/markuprx-3.1.1.tgz', 'markuprx bridge install', 'markuprx bridge token', ]); diff --git a/tests/unit/publicPackageVerification.test.ts b/tests/unit/publicPackageVerification.test.ts index 5aec711..23a0e1b 100644 --- a/tests/unit/publicPackageVerification.test.ts +++ b/tests/unit/publicPackageVerification.test.ts @@ -430,12 +430,12 @@ describe('public package verification', () => { }); it.each([ - 'markuprplus-3.1.0-arm64.dmg', - 'MarkuprPlus-3.1.0-arm64-mac.zip', - 'markuprplus-Setup-3.1.0.exe', - 'MarkuprPlus 3.1.0.exe', - 'markuprplus-3.1.0-x86_64.AppImage', - 'markuprplus-3.1.0-amd64.deb', + 'markuprplus-3.1.1-arm64.dmg', + 'MarkuprPlus-3.1.1-arm64-mac.zip', + 'markuprplus-Setup-3.1.1.exe', + 'MarkuprPlus 3.1.1.exe', + 'markuprplus-3.1.1-x86_64.AppImage', + 'markuprplus-3.1.1-amd64.deb', ])('accepts the canonical filename contract before runtime verification: %s', (name) => { const root = fixture(); writeFileSync(join(root, name), 'fixture'); From a25140f1d6ddcf45bf4634528c8076c8e6b0dfc9 Mon Sep 17 00:00:00 2001 From: hashfunction Date: Sun, 30 Aug 2026 20:21:30 -0700 Subject: [PATCH 2/2] ci: publish companion with releases --- .github/workflows/release.yml | 68 ++++++++++++++++++++++- tests/unit/cliBridgeDocumentation.test.ts | 12 ++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1deb0f9..c5c4d09 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -325,13 +325,65 @@ jobs: if-no-files-found: error retention-days: 30 + # =========================================================================== + # Build CLI/MCP companion package + # =========================================================================== + build-companion: + name: Build CLI Companion + runs-on: ubuntu-latest + needs: validate-tag + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build CLI and MCP entry points + run: | + npm run build:cli + npm run build:mcp + + - name: Pack and verify companion + run: | + set -euo pipefail + VERSION=${{ needs.validate-tag.outputs.version }} + PACKAGE="markuprx-${VERSION}.tgz" + + npm pack + test -f "$PACKAGE" + tar -tzf "$PACKAGE" | grep -Fx 'package/dist/cli/index.mjs' + tar -tzf "$PACKAGE" | grep -Fx 'package/dist/mcp/index.mjs' + + PACKED_VERSION=$(tar -xOf "$PACKAGE" package/package.json \ + | node -e "let value=''; process.stdin.on('data', chunk => value += chunk); process.stdin.on('end', () => process.stdout.write(JSON.parse(value).version));") + test "$PACKED_VERSION" = "$VERSION" + + PREFIX="$RUNNER_TEMP/companion-prefix" + npm install --global --prefix "$PREFIX" "./$PACKAGE" + test "$("$PREFIX/bin/markuprx" --version)" = "$VERSION" + + - name: Upload companion artifact + uses: actions/upload-artifact@v6 + with: + name: release-companion + path: markuprx-${{ needs.validate-tag.outputs.version }}.tgz + if-no-files-found: error + retention-days: 30 + # =========================================================================== # Create GitHub Release # =========================================================================== create-release: name: Create GitHub Release runs-on: ubuntu-latest - needs: [validate-tag, build-macos, build-windows] + needs: [validate-tag, build-macos, build-windows, build-companion] permissions: contents: write steps: @@ -377,6 +429,7 @@ jobs: echo "| macOS (Apple Silicon) | \`markuprplus-${VERSION}-arm64.dmg\` |" >> $NOTES echo "| macOS (Intel) | \`markuprplus-${VERSION}-x64.dmg\` |" >> $NOTES echo "| Windows | \`markuprplus-Setup-${VERSION}.exe\` |" >> $NOTES + echo "| CLI / MCP companion | \`markuprx-${VERSION}.tgz\` |" >> $NOTES echo "" >> $NOTES echo "The macOS builds are signed with a Developer ID Application certificate," >> $NOTES echo "notarized by Apple, and stapled, so they open without a Gatekeeper warning." >> $NOTES @@ -384,7 +437,7 @@ jobs: echo "## Checksums" >> $NOTES echo "" >> $NOTES echo "\`\`\`" >> $NOTES - find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" \) -exec sha256sum {} \; >> $NOTES + find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" -o -name "*.tgz" \) -exec sha256sum {} \; >> $NOTES echo "\`\`\`" >> $NOTES cat $NOTES @@ -407,10 +460,19 @@ jobs: artifacts/release-windows/*.zip artifacts/release-windows/*.blockmap artifacts/release-windows/*.yml + artifacts/release-companion/*.tgz fail_on_unmatched_files: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Verify companion release asset + run: | + VERSION=${{ needs.validate-tag.outputs.version }} + gh release view "$GITHUB_REF_NAME" --json assets --jq '.assets[].name' \ + | grep -Fx "markuprx-${VERSION}.tgz" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Release Summary run: | echo "## Release Summary" >> $GITHUB_STEP_SUMMARY @@ -420,6 +482,6 @@ jobs: echo "**macOS:** signed, notarized, and stapled" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Artifacts" >> $GITHUB_STEP_SUMMARY - find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" \) | while read f; do + find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" -o -name "*.tgz" \) | while read f; do echo "- $(basename $f)" >> $GITHUB_STEP_SUMMARY done diff --git a/tests/unit/cliBridgeDocumentation.test.ts b/tests/unit/cliBridgeDocumentation.test.ts index 24b0de0..c1c0588 100644 --- a/tests/unit/cliBridgeDocumentation.test.ts +++ b/tests/unit/cliBridgeDocumentation.test.ts @@ -35,6 +35,18 @@ describe('CLI Bridge release documentation', () => { expect(readme).toMatch(/App Store app does not (?:run|execute|launch) shell commands/i); }); + it('publishes the versioned companion package as a required release asset', async () => { + const workflow = await readFile('.github/workflows/release.yml', 'utf8'); + + expect(workflow).toMatch(/^ build-companion:$/m); + expect(workflow).toContain('npm run build:cli'); + expect(workflow).toContain('npm run build:mcp'); + expect(workflow).toContain('markuprx-${VERSION}.tgz'); + expect(workflow).toContain('name: release-companion'); + expect(workflow).toContain('artifacts/release-companion/*.tgz'); + expect(workflow).toContain('Verify companion release asset'); + }); + it('discloses bridge data flow in Store copy, privacy copy, and review notes', async () => { const [metadata, reviewNotes, privacyAnswers, privacyPage, changelog] = await Promise.all([ readFile('app-store/metadata/en-US.md', 'utf8'),