Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions doc/launch/issue-16/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Public capture kit

This directory defines the sanitized source material and recording contract for
Markover's focused-preview screenshots and demo. It supports roadmap issue #16
without using a developer's real reviews, repositories, thread history, or
application state.

## Prepare the capture instance

Start from the exact clean commit that should appear in the capture receipt,
then run:

```sh
npm run capture:stage
```

The command resets only its marked directory at
`/tmp/markover-public-capture`, creates five invented reviews across three
disposable Git repositories, applies Ember Light, builds an addressed Markover
bundle, and launches it with production branding. It uses the distinct
`markover-capture` scheme, suppresses protocol registration, and never reads or
writes canonical or development review state.

Use `npm run capture:stage -- --prepare-only` when validating the fixture
without launching the app. The generated `session.json` records the exact
commit, fixture revision, theme, window size, and stable review IDs.

## Capture stills

The four replacement screenshots keep their existing names and Retina contract
so current README and Pages consumers do not need an asset migration. Arrange
these real UI states in the prepared app:

1. `markover-review-editor@2x.png` — Inbox, Needs me, primary launch brief,
heading selected, feedback and both labeled attachments visible.
2. `markover-annotation-browser@2x.png` — Projects, All annotations, primary
launch brief with varied feedback and attachment context.
3. `markover-source-edit@2x.png` — primary opening paragraph selected, Source
expanded, word-level proposal visible.
4. `markover-review-context@2x.png` — primary review with Review context open,
showing only invented project, pull request, commit, and thread metadata.

Each still is 2360×1520 at 144 dpi, captured from the app's 1180×760 logical
window at 2× scale. Keep notifications and unrelated application chrome out of
frame.

## Record the demo

Follow [demo-storyboard.md](demo-storyboard.md). Use `capture:cli` for every
agent-facing Markover command shown in the recording; it addresses only the
running capture service and refuses to start the canonical app implicitly.

```sh
npm --silent run capture:cli -- get mko_capture01 \
| jq -f doc/launch/issue-16/handoff-summary.jq
```

Export a silent, captioned H.264 MP4 at 1920×1080, 30 fps, 30–60 seconds, with
fast-start metadata. The capture PR records the final output path and checksums;
the later media PR owns the actual screenshot and movie binaries.

## Safety checks

Before publishing any visual:

- confirm `session.json` names the intended clean commit;
- confirm Ember + Light and the 1180×760 logical window;
- scan every visible path, repository, pull request, review ID, thread ID, and
machine label against `capture-manifest.json`;
- inspect the four stills and every movie frame for notifications, private
paths, credentials, authorization material, or unrelated application chrome;
- run the deterministic checks documented by the media PR before upload.

The marker file is the deletion boundary. The staging command refuses to
replace an unmarked directory, a symlink, or a fixture whose capture service is
still running.
85 changes: 85 additions & 0 deletions doc/launch/issue-16/capture-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"format": "markover-public-capture",
"version": 1,
"status": "foundation",
"source": {
"redesignPullRequest": 195,
"designBrief": "doc/design/markover-design-brief.md",
"fixtureRevision": 1,
"captureCommit": null
},
"staging": {
"command": "npm run capture:stage",
"stateRoot": "/tmp/markover-public-capture",
"appName": "Markover",
"scheme": "markover-capture",
"palette": "ember",
"appearance": "light",
"registersProtocol": false,
"usesNetworkContent": false
},
"window": {
"logicalWidth": 1180,
"logicalHeight": 760,
"pixelWidth": 2360,
"pixelHeight": 1520,
"densityDpi": 144,
"scaleFactor": 2
},
"fixture": {
"projectRoot": "/tmp/markover-public-capture/projects",
"repositories": [
"https://github.com/markover-demo/atlas-studio.git",
"https://github.com/markover-demo/field-research.git",
"https://github.com/markover-demo/review-protocol.git"
],
"machine": "capture-mac",
"threadHost": "t3code",
"provider": "codex",
"notifications": "disabled"
},
"screenshots": [
{
"filename": "markover-review-editor@2x.png",
"state": "inbox-needs-me-editor-with-two-labeled-attachments",
"consumers": ["README.md", "docs/user/index.html"]
},
{
"filename": "markover-annotation-browser@2x.png",
"state": "projects-all-annotations-with-attachment-context",
"consumers": ["docs/user/index.html"]
},
{
"filename": "markover-source-edit@2x.png",
"state": "expanded-source-card-with-word-level-proposal",
"consumers": ["docs/user/index.html"]
},
{
"filename": "markover-review-context@2x.png",
"state": "review-context-with-sanitized-project-and-thread-metadata",
"consumers": ["docs/user/index.html"]
}
],
"movie": {
"minimumSeconds": 30,
"maximumSeconds": 60,
"width": 1920,
"height": 1080,
"framesPerSecond": 30,
"videoCodec": "h264",
"audio": false,
"fastStart": true,
"captions": "burned-in",
"transcript": "required"
},
"privacy": {
"allowOnlyInventedFixtureData": true,
"forbiddenContent": [
"real home-directory paths",
"real repositories or pull requests",
"real review or thread identifiers",
"credentials or authorization material",
"notifications or unrelated application chrome"
]
}
}
77 changes: 77 additions & 0 deletions doc/launch/issue-16/demo-storyboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Markover focused-preview demo storyboard

## Recording setup

- Prepare the exact clean capture commit with `npm run capture:stage`.
- Record only the sanitized capture instance and a clean terminal at 1920×1080,
30 fps.
- Keep Ember Light selected, notifications off, and all unrelated application
chrome out of frame.
- Export a silent H.264 MP4 between 30 and 60 seconds with burned-in captions
and fast-start metadata.
- Use calm, descriptive language. Do not imply release guarantees or platform
support beyond the current repository documentation.

## Timeline

### 0:00–0:07 — Begin with the review inbox

Show the prepared Inbox with **Needs me** active and open **Launch readiness
brief**. Let the three-pane Ember Light layout establish the review, selected
document block, and feedback pane.

Caption: **Review agent-written Markdown as a document tree.**

### 0:07–0:19 — Add feedback with visual context

Select the heading and reveal its feedback with the two fixture-owned images,
**workflow overview** and **annotation details**. Keep their rewritten Markdown
references visible long enough to read.

Caption: **Attach labeled visual context to one exact block.**

### 0:19–0:30 — Propose an exact source change

Select the opening paragraph and expand Source. Show the existing proposal that
narrows the rollout from everyone to the design-partner group. Hold on the real
word-level diff.

Caption: **Propose an exact edit without changing the source document.**

### 0:30–0:39 — Review every annotation together

Switch to Projects and then **All annotations**. Briefly show the four varied
annotations and their block context in the redesigned browser.

Caption: **Scan the complete review before handing it back.**

### 0:39–0:52 — Retrieve one structured handoff

Return to the terminal and run:

```sh
npm --silent run capture:cli -- get mko_capture01 \
| jq -f doc/launch/issue-16/handoff-summary.jq
```

Show the projected status, feedback, attachment IDs and labels, and source
proposal. The capture CLI addresses only the fixture service and does not start
or inspect canonical Markover state.

Caption: **Return one structured handoff to the agent.**

### 0:52–0:56 — End card

Show the Markover lockup, **Structured review for Markdown**, and
`github.com/lastobelus/markover`.

## Pages transcript

Markover opens a sanitized launch brief in an Ember Light review inbox. The
reviewer selects one Markdown block, adds precise feedback, and keeps two
labeled images attached to that context. On the opening paragraph, Markover
shows an exact source proposal as a word-level diff without changing the source
document. The reviewer switches to All annotations to scan the complete review,
then returns to the agent's terminal. One fixture-only command retrieves a
structured handoff containing the feedback, attachment labels, and source
proposal.
32 changes: 32 additions & 0 deletions doc/launch/issue-16/handoff-summary.jq
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
def reviewed_blocks:
[
..
| objects
| select((.id? // "") | startswith("block-"))
| select(
((.feedback? // "") | length) > 0
or (.sourceEdit? != null)
)
| { id }
+ (if ((.feedback? // "") | length) > 0
then { feedback }
else {}
end)
+ (if ((.attachments? // []) | length) > 0
then {
attachments: [
.attachments[] | { id, label }
]
}
else {}
end)
+ (if .sourceEdit? != null
then { sourceEdit }
else {}
end)
];

{
review: { status: .review.status },
blocks: reviewed_blocks
}
25 changes: 25 additions & 0 deletions doc/launch/issue-16/launch-brief.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Launch readiness brief

Ship the review pilot to everyone as soon as the first workflow is complete.

## Success criteria

- Every handoff names an owner and next action.
- Review feedback stays attached to the relevant Markdown block.
- Source proposals remain explicit and reversible.
- Attachments use clear labels.
- The pilot expands only after the loop is reliable.

## Rollout plan

Start with the design-partner group, observe three complete review loops, and
record blocked or deferred work before expanding.

| Signal | Ready when |
| --- | --- |
| Ownership | Every note has a named owner |
| Reliability | Three handoffs complete without recovery |

```ts
await openReview({ retry: true })
```
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"build": "npm run clean && tsc -p tsconfig.build.json && node build/scripts/copy-build-assets.js && node build/scripts/build-app.js",
"build:icon:mac": "npm run build --silent && node build/scripts/build-macos-icon.js",
"build:cli": "npm run build --silent && node build/scripts/build-cli.js",
"capture:cli": "npm run build --silent && node build/scripts/capture-cli.js",
"capture:stage": "npm run build --silent && node build/scripts/capture-media.js",
"clean": "node -e \"require('node:fs').rmSync('build', { recursive: true, force: true })\"",
"package:mac": "install-electron --no && npm run build:icon:mac && npm run notices:check:built && node build/scripts/package-macos.js --trust-mode=ad-hoc",
"release:preflight": "npm run build --silent && node build/scripts/release-preflight.js",
Expand Down
53 changes: 53 additions & 0 deletions scripts/capture-cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import path from 'node:path'

import {
CAPTURE_ROOT,
CAPTURE_ROOT_MARKER,
CAPTURE_SESSION_RECEIPT
} from './capture-media'
import { main as markoverMain } from './markover'
import { probeService } from '../src/local-client'

async function requireCaptureService(): Promise<void> {
const endpointPath = path.join(CAPTURE_ROOT, 'service.json')
try {
await probeService(endpointPath)
} catch {
throw new Error('The capture instance is not running. Start it with npm run capture:stage.')
}
}

async function main(args = process.argv.slice(2)): Promise<void> {
delete process.env.CLAUDE_CODE_SESSION_ID
delete process.env.CLAUDE_SESSION_ID
delete process.env.CODEX_THREAD_ID
delete process.env.T3CODE_THREAD_ID
delete process.env.T3_THREAD_ID
process.env.MARKOVER_INVOCATION = 'npm --silent run capture:cli --'
await Promise.all([
import('node:fs/promises').then(({ access }) => access(path.join(
CAPTURE_ROOT,
CAPTURE_ROOT_MARKER
))),
import('node:fs/promises').then(({ access }) => access(path.join(
CAPTURE_ROOT,
CAPTURE_SESSION_RECEIPT
)))
]).catch(() => {
throw new Error('The capture fixture is missing. Prepare it with npm run capture:stage.')
})
await markoverMain(args, {
endpointPath: path.join(CAPTURE_ROOT, 'service.json'),
ensure: requireCaptureService,
loadRemoteProfile: () => Promise.resolve(null),
settingsPath: path.join(CAPTURE_ROOT, 'settings.json')
})
}

if (require.main === module) {
void main().catch((error: unknown) => {
const message = error instanceof Error ? error.message : String(error)
process.stderr.write(`markover capture: ${message}\n`)
process.exitCode = 1
})
}
Loading