Skip to content

[codepress#5858 3a] ripple_delete capability, transcript cut, requestTranscription - #17

Merged
lightninglu10 merged 3 commits into
codepress-mainfrom
ve-3a-ripple-transcript-cut
Aug 22, 2026
Merged

[codepress#5858 3a] ripple_delete capability, transcript cut, requestTranscription#17
lightninglu10 merged 3 commits into
codepress-mainfrom
ve-3a-ripple-transcript-cut

Conversation

@lightninglu10

@lightninglu10lightninglu10 commented Aug 22, 2026

Copy link
Copy Markdown

Item 3a of https://github.com/quantfive/codepress/issues/5858 (Video editor v1).

Stacked on #15 (ve-3a0-editorhost-subscribe) — this PR's base is ve-3a0-editorhost-subscribe; retarget to staging once #15 merges.

Why

Cut-via-transcript is a stated product goal that could not be expressed at all:

  • ripple_delete is a real EditCommand with a working engine implementation, but capabilityForCommand returned null for it, so controller.submitEdit rejected the batch as unsupported before it ever reached the host — even though the CodePress host allowlists it.
  • The host transcript editor hardcoded action: 'captions' in its preview request, so captions were the only thing the UI could ever emit.
  • The empty/failed transcript state offered only Retry; nothing could start a transcription.

What changed

src/features/editor/host/contract.ts

  • ripple_delete added to SUPPORTED_HOST_COMMANDS; capabilityForCommand('ripple_delete') now returns 'timeline.remove' (alongside remove_item).
  • New optional EditorTranscriptPort.requestTranscription({ assetId, language? }): HostTranscriptStatusReceipt — signature only, gated by the existing media.transcription capability.
  • Both mirrored in the hand-written packages/freecut-editor/src/index.d.ts.

src/features/editor/host/transcript-editor.tsx

  • The preview action is no longer hardcoded: previewSelection(action) takes the action, and a new Cut selection affordance reuses the existing preview → submitEdit path verbatim with action: 'cut'. 'cut' is the normalized action the CodePress adapter emits (_ACTION_ALIASES maps ripple_cutcut, and preview.action echoes "cut"); the resulting batch is made of ripple_delete commands, which the existing commandIsSupported guard now passes because of the contract change.
  • Apply-button label, preview summary, and the live-region announcements follow the previewed action (Apply cut / Apply captions).
  • The status !== 'succeeded' branch gains a Transcribe affordance, shown only when the port implements requestTranscription and media.transcription is on. It calls the port, then polls getStatus() until the receipt is terminal, and refreshes on succeeded. getStatus() still takes no arguments (one transcript per project) — unchanged by design.
  • Per the standing timer rule, the poll cadence and attempt cap read from VITE_HOST_TRANSCRIBE_POLL_MS (default 3000) and VITE_HOST_TRANSCRIBE_POLL_MAX_ATTEMPTS (default 200).

Version: the package is bumped to 0.3.4. #16 published 0.3.2 and #15 publishes 0.3.3 on merge, so the OIDC publish workflow's already-published guard means this PR must carry its own version for these surface changes to reach the registry. editor.tsx, vite.editor-package.config.ts, export, and the release workflows are untouched.

Tests

  • controller.test.ts: a ripple_delete batch reaches host.submitEdit and lands revision 1; the same batch is gated unsupported when timeline.remove is off; SUPPORTED_HOST_COMMANDS assertion updated.
  • transcript-editor.test.tsx: Cut selection emits a preview request with action: 'cut' and its ripple_delete batch reaches submitEdit; Transcribe appears only when the port implements requestTranscription and the capability is on, and polling reaches succeeded.

Canonical QA report posted as a comment.

…ription
`ripple_delete` is a real EditCommand with a working engine implementation, but
`capabilityForCommand` returned null for it, so `controller.submitEdit` rejected
any transcript cut batch as unsupported before it reached the host. Map it onto
`timeline.remove` and add it to `SUPPORTED_HOST_COMMANDS`.
The host transcript editor hardcoded `action: 'captions'`, so captions were the
only thing the UI could emit. Un-hardcode the preview action and add a "Cut
selection" affordance that reuses the same preview -> submitEdit path with
`action: 'cut'` (the normalized action the CodePress adapter turns into
`ripple_delete` commands).
Add the optional `EditorTranscriptPort.requestTranscription` and a "Transcribe"
affordance in the not-yet-succeeded branch, which polls `getStatus` until the
receipt is terminal. The poll interval and attempt cap read from
`VITE_HOST_TRANSCRIBE_POLL_MS` / `VITE_HOST_TRANSCRIBE_POLL_MAX_ATTEMPTS` with
the production values as defaults.
@lightninglu10

Copy link
Copy Markdown
Author

Canonical QA Report

Verifier revision binding

base: 47e2db3 (origin/staging)
head: 6a75db6
git rev-parse HEAD -> 6a75db6
git status --porcelain -> (empty)

Note: this PR is stacked — its PR base is ve-3a0-editorhost-subscribe (head aca96133, PR #15). qa:binding binds against origin/staging and confirms the head descends from it; inherited failures below were reproduced at the stack base aca96133.

Gate results

#GateResultEvidence
1Head binding✅ PASSqa:binding --check -> clean tree, head descends from base
2Type check✅ PASSnpm run check -> no warnings, lint errors, or type errors in 2445 files
3Lint✅ PASSnpm run lint -> exit 0 (run after build:editor-surface)
4Unit tests❌ FAIL (inherited)npm run test:run -> 45 failed / 637 passed files, 584 failed / 4285 passed tests — identical failure set at base (see below)
5Build✅ PASSnpm run build -> built in 5.03s
6Feature boundaries✅ PASS1675 files scanned, no direct cross-feature imports outside deps/*
7Deps contract boundaries✅ PASS161 deps files scanned, 297 contract files
8Legacy lib imports✅ PASSno unauthorized @/lib/* imports
9Deps wrapper health✅ PASS46 pass-through wrappers, 0 unused
10Unused exports❌ FAIL (inherited)129 findings, 119 allowlisted, 10 new, 3 stale — byte-identical to base; no allowlist edited
11Unused class members❌ FAIL (inherited)83 findings, 83 allowlisted, 0 new, 2 stale — identical to base; no allowlist edited
12Changed-health✅ PASS9 changed files; introduced dead_code=0, complexity=0, duplication=0
13Edge budgets✅ PASSall tracked edges within budget
14Provenance/reproducibility✅ PASSsource + MIT/notices + dependency (51 runtime, 16 dev) + asset inventory (5 roots) verified
15Editor-surface package build✅ PASSnpm run build:editor-surface -> built in 13.33s
16Installed consumer smoke✅ PASSpacked + installed @quantfive/freecut-editor-surface@0.3.3, consumer test 1 passed
17Headless contract tests (Node)✅ PASS43 pass / 0 fail
18Browser QA✅ PASSsystem Chrome 151.0.7922.172; harness ready, renderFrame ok, frame width match, PNG >1KB
19Full headless browser suite✅ PASS19 edit-operation contracts + lifecycle HTTP/CLI import/edit/render passed
20Redaction✅ PASScheck:qa-redaction clean + fail-closed self-test 6 pass / 0 fail

Also run: npm run package:editor-surface -> artifacts/freecut-editor-surface-0.3.3.tgz, sha256 f144c625e26ec2ff20429c68d0d4ff7a26ba86bcaf8e9878d99d0264a66ac946 (never published from QA).

Inherited baseline failures

  • Gate 4 (npm run test:run): FAIL at stack base aca961335d9856fe6e5059950646f6ca0bbf9d2a with the jsdom/localStorage set — TypeError: Cannot read properties of undefined (reading 'setItem') from the zustand persist middleware. Reproduced at the base SHA in a detached worktree: base = 45 failed / 637 passed files, 584 failed / 4280 passed tests; head = 45 failed / 637 passed files, 584 failed / 4285 passed tests. Same failing files and same failure count; the +5 passes are this PR's 5 new tests. Not caused by this PR; nothing skipped or allowlisted.
    • Includes the 3 pre-existing failures in the touched file src/features/editor/host/transcript-editor.tsx's test (transcript tab across authoritative snapshots (real MediaSidebar path)), which fail identically at base via EmbeddedEditorHostRuntime.unmountStores -> playback/store.ts persist.
  • Gate 10 (check:unused-exports): FAIL at base aca96133 — 129 findings, 119 allowlisted, 10 new, 3 stale. Output byte-identical at base and head; allowlists are ratchet baselines and were not touched.
  • Gate 11 (check:unused-class-members): FAIL at base aca96133 — 83 findings, 83 allowlisted, 0 new, 2 stale. Identical at base and head; allowlist untouched.

Environment blockers

  • None. A real browser session (system Chrome, channel chrome) was available for gates 18–19.

Visual / browser artifacts

  • artifacts/qa/browser-6a75db6461f6/manifest.json (+ frame.png, harness.png, console.log)

Overall

✅ PASS — PENDING JUDGE

(Gates 4, 10, 11 are disclosed inherited baseline failures reproduced at the stack base; no new failure is introduced by this PR.)

No merge until trusted judge PASS.

@lightninglu10

Copy link
Copy Markdown
Author

@codepress /judge-verification can you judge this verification?

@codepress-dev

Copy link
Copy Markdown

👋 Hey @lightninglu10! Spawning a verification judge session to help with your request. View session

@codepress-dev

Copy link
Copy Markdown

@Terminal@lightninglu10

Dispatched by judge-verification.

Work the Path to merge below. Reuse healthy exact-head verification environments; do not redeploy or restart unless stale or unhealthy.

Continue only when there is meaningful work to clear the blocker. If the path is already satisfied, the same blocker remains, or another judge pass would add no useful evidence, stop and report that instead of submitting another verification report.

Verification Judgment — PR #17 (local)

Verdict: ❌ NOT READY TO MERGE

PR Head SHA:6a75db6461f63821090d11e0824c277627e04dee

Summary: The canonical report is bound to the live PR head and records a clean verifier checkout. Its deterministic evidence supports the new ripple_delete capability mapping and the public editor-surface contract, but it does not establish the two new user-facing transcript flows. The cited browser/headless checks are generic and contain no transcript-host trigger or outcome, while the changed component tests use a fake host. A fresh feature-specific live UI verification is required.

Revision binding

  • Classification: SAME-SHA LATE BINDING
  • Report head:6a75db6461f63821090d11e0824c277627e04dee
  • Live PR head:6a75db6461f63821090d11e0824c277627e04dee
  • Audited checkout: clean detached checkout at 6a75db6461f63821090d11e0824c277627e04dee
  • Concrete evidence: The canonical report comment ([codepress#5858 3a] ripple_delete capability, transcript cut, requestTranscription #17 (comment)) records head: 6a75db6461f63821090d11e0824c277627e04dee; git rev-parse HEAD -> 6a75db6461f63821090d11e0824c277627e04dee; git status --porcelain -> (empty). A live PR lookup returned the same headRefOid; the judge audited a separate clean detached checkout at that SHA.
  • Rows carried forward: none
  • Rows reverified at live head: none
  • Rows still requiring verification: G1, G2
  • Publication timing: The report comment was created at 2026-08-22T18:56:31Z, after the head commit at 2026-08-22T18:52:45Z and before the judgment request at 2026-08-22T20:04:58Z. GitHub still resolves the PR to the same head. This timing establishes report/head ordering only; the captured verifier commands above establish verifier checkout state.

Diff trigger inventory

SurfaceLocationCoverage
ripple_delete becomes an accepted host command mapped to timeline.remove, including capability denialsrc/features/editor/host/contract.ts:321-351; src/features/editor/host/controller.test.ts:367-4261
The public editor-surface contract exposes the new command and optional transcription requestpackages/freecut-editor/src/index.d.ts:289-294,382-390; packages/freecut-editor/README.md:29-392
Transcript cut is a real user flow: select sections, preview without timeline mutation, then apply through the host as ripple_deletesrc/features/editor/host/transcript-editor.tsx:640-765,1028-1054; src/features/editor/host/transcript-editor.test.tsx:364-392G1
Transcription request is gated, starts through the host, polls pending/running receipts, and handles terminal completion or failuresrc/features/editor/host/transcript-editor.tsx:767-865; src/features/editor/host/transcript-editor.test.tsx:394-448,514-537G2

Per-item

#Verifier saidJudgmentEvidence
1PASS✅ PASSThe diff adds ripple_delete to SUPPORTED_HOST_COMMANDS and maps it to timeline.remove. The controller tests exercise an applied batch and the capability-off rejection. The report also states that the base/head unit-test failure set is identical and that the head has five additional passing tests, matching the five new tests added by this diff.
2PASS✅ PASSThe report records successful editor-surface package build and installed-consumer smoke gates. The changed declaration includes the optional requestTranscription method and ripple_delete in the supported command tuple, so the package boundary is covered at the exact head.
G1PASS (generic browser gate)❌ GAPThe report's browser evidence only says that a harness rendered successfully and that generic edit-operation/lifecycle checks passed. The repository headless and browser QA sources contain no host-transcript, ripple_delete, or requestTranscription exercise. The changed React test drives a fake host, so it does not establish the real Media/Transcript sidebar flow: selecting a section, observing a non-mutating cut preview, applying it, and observing the host/timeline consequence. The cited browser artifact is only a relative local path, which is also an unpublishable visual-evidence form gap.
G2PASS (generic browser gate)❌ GAPNo cited live observation exercises the new Transcribe affordance, the host request arguments, pending/running polling to a succeeded receipt, or the capability/port and terminal-state gates. The component test uses a fake transcription port and the generic browser suite has no matching surface/API references.

Overall status check

  • Verifier said: PASS
  • Result: NOT READY TO MERGE

Path to merge

RowClassOwnerAction that clears it
G1verification-gapverifierRun a fresh exact-head browser/UI check through the real Media/Transcript sidebar: load a succeeded transcript, select a section, click Cut selection, confirm the preview leaves the timeline unchanged, apply it, and capture the resulting host submission/timeline state plus the capability-off or rejection outcome. Publish durable evidence for the feature-specific observation.
G2verification-gapverifierRun a fresh exact-head browser/UI check with a host implementing requestTranscription: click Transcribe from the unavailable state, capture the asset/language request, observe pending/running polling through terminal success and refreshed sections, and cover the missing-port or capability-off and terminal-failure states. Publish durable evidence for the feature-specific observation.

Becomes ✅ READY TO MERGE when: G1 and G2 have feature-specific live evidence from a fresh report bound to 6a75db6461f63821090d11e0824c277627e04dee, with the report reposted at that exact head and no new blocking result.

Dispatch: yes

What stood up

  • Exact-head same-SHA binding is supported by the report's captured revision and clean-tree commands and by a separate clean detached judge checkout.
  • The controller capability mapping and installed package boundary have concrete exact-head deterministic evidence.
  • The report's disclosed inherited failures remain the same at the stack base and head; they were not used as blockers for rows 1 or 2.

#15 publishes 0.3.3 when it merges, and the OIDC publish workflow's
already-published guard refuses a second publish at the same version. This PR
therefore has to carry its own version for its surface changes (the
ripple_delete capability, the transcript cut action, and the optional
requestTranscription port) to reach the registry.
@lightninglu10

Copy link
Copy Markdown
Author

@codepress /judge-verification can you judge this verification?

Local Verification

PR Head SHA:63bad2b63d05702802284c5e520531d3811df3c5

What changed since the last judgment. The previous judgment (comment
5382398382's sibling on this PR) returned NOT READY at head 6a75db64 with
two verification gaps: G1 (transcript cut is a real user flow) and G2
(transcription request + polling), both marked "generic browser gate, no
feature-specific live observation; the changed React test drives a fake host".
Rows 1 and 2 passed there and are unchanged.

Two things happened since. First, the two gap rows were closed with a fresh
live UI run against the real packed artifact — details below. Second, the
orchestrator instructed a version bump to 0.3.4: freecut#16 already
published 0.3.2, freecut#15 publishes 0.3.3 on merge, and the OIDC workflow's
already-published guard would refuse this PR's publish at a duplicate version.
That bump is the only commit added (63bad2b6), so every row below was
re-captured at this new head
— nothing is carried forward from 6a75db64.

Verifier revision binding

  • git rev-parse HEAD -> 63bad2b63d05702802284c5e520531d3811df3c5
  • git status --porcelain -> (empty)

Captured from npm run qa:binding -- --check: "OK: clean tree, head descends
from base"; base 47e2db3c2d5a6148cb9137f3a2a21836322568a7 (origin/staging).
This PR is stacked: its PR base is ve-3a0-editorhost-subscribe (freecut#15,
head aca961335d9856fe6e5059950646f6ca0bbf9d2a), and every inherited-baseline
claim below was reproduced at that stack base in a separate detached worktree.

Diff Trigger Inventory

SurfaceLocationContract
ripple_delete becomes an accepted host command mapped to timeline.removesrc/features/editor/host/contract.ts:311,338-340Row 1
Public editor-surface declaration exposes the command and the optional transcription requestpackages/freecut-editor/src/index.d.ts:291-294,383Row 2
Transcript cut is a real user flow: select, preview without mutation, apply as ripple_deletesrc/features/editor/host/transcript-editor.tsx:641-714,1030-1060Row G1
Transcription request is gated, starts through the host, polls to a terminal receiptsrc/features/editor/host/transcript-editor.tsx:766-864,414-455Row G2
Poll cadence knob with the production value as defaultsrc/features/editor/host/transcript-editor.tsx:51-78Row G3
Published version carries its own release slotpackages/freecut-editor/package.json:3Row 3

Verification Contract Results

How G1/G2/G3 were exercised.npm run package:editor-surface produced
artifacts/freecut-editor-surface-0.3.4.tgz, sha256
4ccbc792cba177c9084690c0b3bf386e877ee175639c458b5285b4e8a5d27e47
(byte-identical across two consecutive runs). That tarball was installed with
npm install <tgz> into a fresh consumer app, which mounts FreeCutEditorSurface
exactly as the CodePress web app will and drives it in system Chrome
151.0.7922.172
via Playwright — the real MediaSidebar, the real Transcript
tab, real clicks on real controls. Nothing inside the package is mocked: the
only test double is the EditorHost implementation, which is the caller-supplied
port the contract exists for. 25/25 live checks passed.

Negative control (anti-vacuity). The identical consumer app and identical
host were run a second time against a tarball packed from the stack base
aca96133 (0.3.3, sha256 9f0e3da0b32f4fae67b6d3d6004b06f8c89a42bbe082b0e161535fa02194cdd7
— the same digest freecut#15's report cites for that artifact). All 7 control
expectations held: on the base surface there is no Cut selection affordance,
no Transcribe affordance, requestTranscription is never called, the
preview action is hardcoded captions, and the apply button can only ever read
"Apply captions". The base caption flow still completes end to end, so the
harness is sound and the G1/G2 results are not passing vacuously.

#AssertionResultEvidence
1ripple_delete is an accepted host command mapped to timeline.remove, and is gated when that capability is offPASScapabilityForCommand('ripple_delete') -> 'timeline.remove'; a ripple_delete batch reaches host.submitEdit and lands revision 1; the same batch returns unsupported with submitEdit never called when timeline.remove is false. vp test run src/features/editor/host/controller.test.ts -> 19/19
2The published declaration exposes ripple_delete and optional requestTranscriptionPASSSUPPORTED_HOST_COMMANDS and EditorTranscriptPort.requestTranscription? present in the installednode_modules/@quantfive/freecut-editor-surface/dist/index.d.ts; test:editor-surface:consumer installs 0.3.4 into a fresh fixture, 1/1
G1Transcript cut is a real user flow: preview leaves the timeline untouched, apply submits ripple_delete, and the host timeline ripplesPASSLive, installed 0.3.4 in Chrome. Transcript tab offered; timeline starts revision 0 / one 120-frame clip. Selecting section 1 and clicking Cut selection sends action: 'cut' with exactly [{startUs:1000000,endUs:2000000}]. During preview: submitEdit calls = 0, revision still 0, apply button reads "Apply cut" (g1-03, sha256 dcdde579a1ce…). After Apply cut: batch reaches host.submitEdit as ["ripple_delete"] over 1000000..2000000, host timeline goes revision 0 -> 1, durationInFrames120 -> 90, the clip shortens, the header reads 4s -> 3s and Properties reads Total Frames 120 fr -> 90 fr (g1-04, sha256 3f9b415a317a…). Live region announces "Transcript cut applied."
G1bA cut is refused when timeline.remove is off, and never reaches the hostPASSLive. The host still returns a well-formed action: 'cut' preview, so the refusal comes from the surface's own capability gate, not a host failure: the UI shows "The transcript preview could not be prepared.", no preview panel renders, submitEdit calls = 0, timeline stays revision 0 / 120 frames (g1-05, sha256 5fe9ff80365a…)
G2Transcribe starts a host transcription and polls to a succeeded receiptPASSLive. From the unavailable state the Transcribe affordance renders (g2-01, sha256 7338fa810233…); clicking it calls requestTranscription({assetId:'asset-1',language:'en'}); the surface then polls getStatus through pending -> running -> succeeded and refreshes into the real section list with status succeeded and 2 sections (g2-03, sha256 749eb0738349…)
G2bThe affordance is gated on both the port and the capability, and terminal failures stop pollingPASSLive. Host withoutrequestTranscription -> no Transcribe affordance, unavailable state otherwise unchanged (g2-04, sha256 64316bbbab00…). media.transcriptionoff -> the Transcript tab is not offered at all (g2-05, sha256 323fe6785cc6…). A terminal failed receipt -> polling stops (3 getStatus calls, not spinning), the host error surfaces, and Transcribe is re-enabled for retry (g2-06, sha256 28b75818323a…)
G3The poll cadence reads from an env knob with the production value as defaultPASSSource: VITE_HOST_TRANSCRIBE_POLL_MS (default 3000) and VITE_HOST_TRANSCRIBE_POLL_MAX_ATTEMPTS (default 200); the unit tests compress it via vi.stubEnv. Statically confirmed in the shipped bundle: dist/index.js inlines Ud = 3e3, Wd = 200. Observed live at the production default — the G2 run took 6391 ms across 4 getStatus calls, i.e. the real 3 s cadence, not a test-compressed one
3The package carries its own publishable versionPASSpackage:editor-surface -> version 0.3.4, sha256 4ccbc792…d27e47, identical across two runs; fresh-consumer install reports @quantfive/freecut-editor-surface@0.3.4
4TypecheckPASSnpm run check -> 0 errors across 2445 files
5LintPASSnpm run lint -> exit 0
6BuildPASSnpm run build -> built
7Changed-healthPASS9 changed files vs base; introduced dead_code=0, complexity=0, duplication=0
8Architecture gatesPASSboundaries (1675 files), deps-contracts (161/297), legacy-lib-imports, deps-wrapper-health (46/0), edge-budgets
9ProvenancePASSverify:provenance -> license/notices, 51 runtime + 16 dev deps, 5 asset roots
10Headless contracts (Node)PASS43/43
11Headless browser suitePASS19/19 edit-operation contracts + lifecycle HTTP/CLI import/edit/render
12Browser QA gatePASSreal system Chrome 151.0.7922.172, 4/4; artifacts/qa/browser-63bad2b63d05/ manifest digests: frame.png 8206275c7f9794b6…, harness.png 2360d2cc7439d7cb…
13QA redactionPASScheck:qa-redaction clean + 6/6 fail-closed self-tests
14Focused in-repo tests for this diffPASSvp test run src/features/editor/host/transcript-editor.test.tsx src/features/editor/host/controller.test.ts -> 27 passed, plus the 3 inherited failures listed below
15Full unit suiteFAIL — inherited baselinejsdom/localStorage zustand-persist crash. Stack base aca96133: 45 failed files / 584 failed / 4280 passed. This head: 45 failed files / 584 failed / 4285 passed. Same failing files, same failure count; the +5 passes are exactly this PR's 5 new tests. Reproduced at the base SHA in a detached worktree; no allowlist, skip list, or config edited
16Unused exports ratchetFAIL — inherited baseline"129 findings, 119 allowlisted, 10 new, 3 stale" — output identical at base aca96133 and this head; none of the 10 is in a file this PR touches; allowlist untouched
17Unused class members ratchetFAIL — inherited baseline"83 findings, 83 allowlisted, 0 new, 2 stale" — identical at base aca96133 and this head; allowlist untouched

Rows 15–17 are the three disclosed failures, recorded as failures per
docs/qa/README.md's "baseline failures are disclosed, never hidden" rule and
each reproduced at the stack base. The previous judgment examined them and did
not treat them as blockers for any row.

Evidence artifacts. Screenshots, the per-check results, and the negative-control
results are written with sha256 digests to a gitignored local QA directory per
docs/qa/README.md; the digests are inlined above rather than cited by path, and
the observable content of each screenshot is described inline in the row it
supports. No secrets, tokens, absolute local paths, or media bytes appear in this
report.

Scope note. The published bundle inlines import.meta.env, so the poll knob
resolves to its production default inside the packaged surface (row G3 shows the
literal 3e3/200 in dist/index.js and the observed 3 s live cadence). The
override is effective for source builds and tests; it is not runtime-configurable
by a consumer of the prebuilt package. That is disclosed rather than claimed
otherwise.

Overall: PASS

@codepress-dev

Copy link
Copy Markdown

👋 Hey @lightninglu10! Spawning a verification judge session to help with your request. View session

@lightninglu10
lightninglu10 changed the base branch from ve-3a0-editorhost-subscribe to codepress-mainAugust 22, 2026 20:43
@codepress-dev

Copy link
Copy Markdown

@Terminal@lightninglu10

Dispatched by judge-verification.

This judgment is READY TO MERGE at the current head. If the PR is still a draft, transition it to ready for review now with the guarded readiness transaction: codepress-policy ready-for-review --repo . --pr 17 (or node packages/delivery-policy/dist/cli.js ready-for-review --repo . --pr 17 when the CLI is not on PATH). It re-validates current-head QA and judge evidence, reconciles the delivery-status marker, and marks the PR ready so the native reviewer can dispatch. Do not call gh pr ready directly, and do not merge; merge authorization still requires the reviewer gate.

Verification Judgment — PR #17 (local)

Verdict: ✅ READY TO MERGE

PR Head SHA:63bad2b63d05702802284c5e520531d3811df3c5

Summary: The report is bound to the live PR head, the verifier captured a clean checkout, and feature-specific live checks against the packed 0.3.4 artifact establish the transcript cut, capability gate, host transcription request, polling, and terminal-state behavior. The three disclosed suite/ratchet failures reproduce at the stack base and are immaterial to the inventoried change.

Revision binding

  • Classification: SAME-SHA LATE BINDING
  • Report head:63bad2b63d05702802284c5e520531d3811df3c5
  • Live PR head:63bad2b63d05702802284c5e520531d3811df3c5
  • Audited checkout: clean detached checkout at 63bad2b63d05702802284c5e520531d3811df3c5
  • Concrete evidence: Verifier capture: git rev-parse HEAD -> 63bad2b63d05702802284c5e520531d3811df3c5; git status --porcelain -> (empty). Judge capture from a separate detached checkout: git rev-parse HEAD -> 63bad2b63d05702802284c5e520531d3811df3c5; git status --porcelain -> (empty).
  • Rows carried forward: none
  • Rows reverified at live head: none
  • Rows still requiring verification: none
  • Publication timing: GitHub shows the live head commit at 2026-08-22T20:27:15Z and the report comment at 2026-08-22T20:38:47Z; the live PR lookup still returns the same full head. This timing establishes report/head ordering only; the captured verifier commands establish verifier checkout state.

Diff trigger inventory

SurfaceLocationCoverage
ripple_delete is accepted by the host command contract and mapped to timeline.remove, including capability denialsrc/features/editor/host/contract.ts:318-364; src/features/editor/host/controller.test.ts:367-4261
The published editor-surface declaration exposes ripple_delete and optional requestTranscriptionpackages/freecut-editor/src/index.d.ts:289-391; packages/freecut-editor/README.md:29-402
Transcript cut selects ranges, previews without mutation, applies through the host, and refuses when removal capability is offsrc/features/editor/host/transcript-editor.tsx:640-765,988-1055; live packed-artifact flowG1, G1b
Transcription request is gated, starts through the host, polls pending and running receipts, and handles terminal success or failuresrc/features/editor/host/transcript-editor.tsx:767-865; live packed-artifact flowG2, G2b
Poll cadence and attempt cap use environment values with production defaultssrc/features/editor/host/transcript-editor.tsx:51-78G3
The package carries a distinct publishable release slotpackages/freecut-editor/package.json:33
Deterministic build, contract, architecture, provenance, redaction, and focused-test gatesReport rows 4-11 and 13-17; changed files and package artifact4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17
Browser QA gate for the packed surfaceReport row 12 and live system Chrome evidence12

Per-item

#Verifier saidJudgmentEvidence
1PASS✅ PASSThe diff adds ripple_delete to the supported command list and maps it to timeline.remove. The report records an applied batch reaching host.submitEdit, revision 1, and an off-capability rejection before host submission; the focused controller test reports 19/19.
2PASS✅ PASSThe fresh consumer install of @quantfive/freecut-editor-surface@0.3.4 exposes ripple_delete and optional requestTranscription in the installed declaration; the consumer contract check reports 1/1.
G1PASS✅ PASSIn system Chrome 151 against the installed 0.3.4 artifact, the real Media and Transcript surface sends action: 'cut' with the selected one-second range, makes zero submitEdit calls during preview, keeps revision 0, then applies a ripple_delete batch and observes revision 0 to 1, 120 to 90 frames, a shortened clip, and the Transcript cut applied. announcement.
G1bPASS✅ PASSWith timeline.remove disabled, the live surface rejects the otherwise well-formed cut preview, renders the preparation error, makes zero submitEdit calls, and leaves revision 0 and 120 frames unchanged.
G2PASS✅ PASSThe live unavailable state renders Transcribe; clicking it calls requestTranscription({assetId:'asset-1',language:'en'}), then observes getStatus through pending to running to succeeded and refreshes the real section list to succeeded with two sections.
G2bPASS✅ PASSThe live run hides Transcribe without the port, removes the Transcript tab with media.transcription off, and on a terminal failed receipt stops polling after three status calls, surfaces the host error, and re-enables retry.
G3PASS✅ PASSThe source defines VITE_HOST_TRANSCRIBE_POLL_MS and VITE_HOST_TRANSCRIBE_POLL_MAX_ATTEMPTS with defaults 3000 and 200; the shipped bundle contains the corresponding 3e3 and 200 values, and the live production-default run took 6391 ms across four status calls.
3PASS✅ PASSThe package manifest and fresh artifact both report version 0.3.4; the package tarball was byte-identical across two consecutive builds and installed successfully in the consumer.
4PASS✅ PASSnpm run check reported zero errors across 2445 files.
5PASS✅ PASSnpm run lint exited 0.
6PASS✅ PASSnpm run build completed successfully.
7PASS✅ PASSThe changed-health scan reported dead_code=0, complexity=0, and duplication=0 for the reported nine-file change set.
8PASS✅ PASSBoundary, dependency-contract, legacy-import, wrapper-health, and edge-budget gates all passed.
9PASS✅ PASSProvenance verification passed for licenses and notices, 51 runtime dependencies, 16 development dependencies, and five asset roots.
10PASS✅ PASSHeadless Node contracts reported 43/43.
11PASS✅ PASSThe headless browser suite reported 19/19 edit-operation and lifecycle checks.
12PASS✅ PASS (FORM CAVEAT)Real system Chrome 151 browser QA reported 4/4 and included manifest digests. Advisory form caveat: the referenced screenshot artifacts are only local gitignored files and are not published at a durable URL, so the visual proof is not independently retrievable; the inline runtime observations above remain concrete.
13PASS✅ PASSQA redaction passed, including six fail-closed self-tests.
14PASS✅ PASSThe focused transcript-editor and controller run reported 27 passing tests; the report separately identifies the three inherited teardown failures.
15FAIL — inherited baseline✅ WAIVEDThe full-suite failure is the same 45-file and 584-test jsdom/localStorage zustand-persist crash at stack base aca961335d9856fe6e5059950646fca0bbf9d2a and this head. The focused changed-surface tests pass and live checks cover the new flows, so this unchanged environment teardown failure does not bear on the inventoried behavior.
16FAIL — inherited baseline✅ WAIVEDThe unused-export ratchet output is identical at the stack base and head, with the allowlist untouched and none of the ten new-to-ratchet findings in a changed file. It does not indicate a new export defect in this PR.
17FAIL — inherited baseline✅ WAIVEDThe unused-class-member ratchet output is identical at the stack base and head, with no new findings and the allowlist untouched. It does not indicate a new class-member defect in this PR.

Overall status check

  • Verifier said: PASS
  • Result: READY TO MERGE

What stood up

  • Same-SHA binding is supported by explicit verifier git rev-parse HEAD and empty git status --porcelain capture, plus a separate clean detached audit checkout.
  • The live packed-artifact run directly exercised the real Transcript UI, host request port, polling loop, capability gates, preview/apply boundary, and resulting timeline state.
  • The inherited failures are disclosed and reproduced at the stack base rather than hidden or newly introduced.

@lightninglu10
lightninglu10 marked this pull request as ready for review August 22, 2026 20:45
@codepress-reviewer-dev

Copy link
Copy Markdown

Starting initial review of 63bad2b6 from baseline aca96133... 👀

View automation run

@codepress-reviewer-devcodepress-reviewer-devBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: the host-preview boundary needs one more semantic check before this enables a destructive command.

previewSelection records the action the user chose, but it accepts any capability-enabled command batch returned by the host. A captions request that mistakenly returns a ripple_delete batch now passes commandIsSupported, is shown as “Apply captions,” and can remove timeline content when applied. Previously that bad response was stopped because ripple_delete was unsupported.

Please reject previews whose normalized returned action or command family does not match the requested action before storing them as a preview, and add a regression test for that mismatched captions response. The existing host-owned preview → explicit apply shape otherwise remains appropriate.

Reviewed `aca96133`...`63bad2b6`. Diff collection and GitHub posting were handled by the automation.

View automation run

@codepress-reviewer-dev

codepress-reviewer-devBot commented Aug 22, 2026

Copy link
Copy Markdown

Review head 33ef952521cd0da1d885520eeac60d816084496c; round 2; 7 reviewed file(s), 0 pending/skipped file(s). 1 subsystem record(s) retained; 0 omitted.

View automation run

… for
previewSelection recorded the requested action but then accepted any batch the
host returned as long as every command was capability-enabled. Making
ripple_delete capability-enabled removed the fail-closed behavior that used to
stop a mismatched batch: a captions request answered with a ripple_delete batch
now passed commandIsSupported, was labeled "Apply captions", and deleted
timeline content when applied.
Reject a preview before it is stored unless it matches the requested action --
the echoed action, when the host sends one, and every command in the batch
against that action's command family (ripple_delete for cut, caption commands
for captions). A mismatch surfaces as a non-retryable
transcript_preview_action_mismatch validation error, so no preview is stored and
there is nothing to apply.
@codepress-reviewer-dev

Copy link
Copy Markdown

Starting new changes review of 33ef9525 from baseline 63bad2b6... 👀

View automation run

@codepress-reviewer-devcodepress-reviewer-devBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preview/apply boundary now has the missing semantic check: the surface normalizes the requested and echoed actions, constrains each action to its allowed command family, and rejects a mismatch before storing a preview. The added regression cases cover the captions-to-ripple-delete path, the inverse command-family mismatch, and an incorrect action echo. This keeps preview creation with the host while ensuring the UI never labels a destructive batch as captions.

Approved with one nonblocking follow-up:

  • Warning — src/features/editor/host/transcript-editor.tsx:846: polling is not cancelled when the Transcript component unmounts. Switching away from the real Transcript tab unmounts this component, but an active request can continue calling getStatus() for up to 200 attempts. Invalidate the generation in unmount cleanup (and preferably cancel the outstanding delay), with a test that confirms polling stops after unmount.
Reviewed `63bad2b6`...`33ef9525`. Diff collection and GitHub posting were handled by the automation.

View automation run

@lightninglu10

Copy link
Copy Markdown
Author

@codepress /judge-verification can you judge this verification?

Local Verification

PR Head SHA:33ef952521cd0da1d885520eeac60d816084496c

What changed since the last judgment. The previous judgment returned PASS at
head 63bad2b6. After it, @codepress-reviewer-dev returned CHANGES_REQUESTED
with one valid finding: previewSelection recorded the requested action but
accepted any capability-enabled batch the host returned, so a captions
request that came back as a ripple_delete batch would pass commandIsSupported,
be labelled "Apply captions", and delete timeline content on apply — a hazard
this PR itself created by making ripple_delete supported.

33ef9525 is the single commit fixing that: previews are now rejected before
being stored unless the normalized echoed action and the command family of
the batch
both match what the user asked for (ripple_delete for cut, the
caption command family for captions), surfaced as a non-retryable validation
error. Version stays 0.3.4. Every row below was re-captured at this head
— nothing is carried forward from 63bad2b6 — and a new row G4 exercises
the fix live. The same reviewer has since APPROVED this head.

Verifier revision binding

  • git rev-parse HEAD -> 33ef952521cd0da1d885520eeac60d816084496c
  • git status --porcelain -> (empty)

npm run qa:binding -- --check: "OK: clean tree, head descends from base". This
PR is stacked; every inherited-baseline claim below was reproduced at the stack
base aca961335d9856fe6e5059950646f6ca0bbf9d2a in a separate detached worktree
with its own install.

Diff Trigger Inventory

SurfaceLocationContract
ripple_delete becomes an accepted host command mapped to timeline.removesrc/features/editor/host/contract.ts:326,348-350Row 1
Public editor-surface declaration exposes the command and the optional transcription requestpackages/freecut-editor/src/index.d.tsRow 2
Transcript cut is a real user flow: select, preview without mutation, apply as ripple_deletesrc/features/editor/host/transcript-editor.tsx (previewSelection, applyPreview, footer)Row G1
A returned preview must match the requested action and command family before it is storedsrc/features/editor/host/transcript-editor.tsx (normalizeTranscriptAction, assertPreviewMatchesAction, TranscriptPreviewMismatchError)Row G4
Transcription request is gated, starts through the host, polls to a terminal receiptsrc/features/editor/host/transcript-editor.tsx (startTranscription, UnavailableTranscript)Row G2
Poll cadence knob with the production value as defaultsrc/features/editor/host/transcript-editor.tsx (transcribePollIntervalMs, transcribePollMaxAttempts)Row G3
Published version carries its own release slotpackages/freecut-editor/package.json:3Row 3

Verification Contract Results

How G1/G2/G3/G4 were exercised.npm run package:editor-surface produced
freecut-editor-surface-0.3.4.tgz, sha256
6228164aeaa23eac4f09fe8fc4fce6528a8c4ba99c6ce50f73d22a06696a0c95
(byte-identical across two consecutive runs). That tarball was installed with
npm install <tgz> into a fresh consumer app, which mounts FreeCutEditorSurface
exactly as the CodePress web app will and drives it in system Chrome
151.0.7922.172
via Playwright — the real MediaSidebar, the real Transcript
tab, real mouse clicks on real controls. Nothing inside the package is mocked:
the only test double is the EditorHost implementation, which is the
caller-supplied port the contract exists for. 29/29 live checks passed at this
head (25/25 at the previous head plus the 4 new G4 checks).

Negative control (anti-vacuity). The identical consumer app and identical host
were run a second time against a tarball packed from the stack base
aca96133 (0.3.3, sha256
9f0e3da0b32f4fae67b6d3d6004b06f8c89a42bbe082b0e161535fa02194cdd7 — the same
digest freecut#15's report cites for that artifact). All 7 control expectations
held: on the base surface there is no Cut selection affordance, no
Transcribe affordance
, requestTranscription is never called, the preview
action is hardcoded captions, and the apply button can only ever read "Apply
captions". The base caption flow still completes end to end, so the harness is
sound and the results below are not passing vacuously.

#AssertionResultEvidence
1ripple_delete is an accepted host command mapped to timeline.remove, and is gated when that capability is offPASScapabilityForCommand('ripple_delete') -> 'timeline.remove'; a ripple_delete batch reaches host.submitEdit and lands revision 1; the same batch returns unsupported with submitEdit never called when timeline.remove is false. vp test run src/features/editor/host/controller.test.ts -> 19/19
2The published declaration exposes ripple_delete and optional requestTranscriptionPASSSUPPORTED_HOST_COMMANDS and EditorTranscriptPort.requestTranscription? present in the installednode_modules/@quantfive/freecut-editor-surface/dist/index.d.ts; test:editor-surface:consumer installs 0.3.4 into a fresh fixture, 1/1
G1Transcript cut is a real user flow: preview leaves the timeline untouched, apply submits ripple_delete, and the host timeline ripplesPASSLive, installed 0.3.4 in Chrome. Transcript tab offered; timeline starts revision 0 / one 120-frame clip (g1-01, sha256 fccb0c5aece5…). Selecting section 1 and clicking Cut selection sends action: 'cut' with exactly [{startUs:1000000,endUs:2000000}]. During preview: submitEdit calls = 0, revision still 0, apply button reads "Apply cut" (g1-03, sha256 fd7d7154ac11…). After Apply cut: the batch reaches host.submitEdit as ["ripple_delete"] over 1000000..2000000, the host timeline goes revision 0 -> 1, durationInFrames120 -> 90, the clip shortens, the header reads 4s -> 3s and Properties reads Total Frames 120 fr -> 90 fr (g1-04, sha256 1d6ce52e1b18…). The live region announces "Transcript cut applied."
G1bA cut is refused when timeline.remove is off, and never reaches the hostPASSLive. The host still returns a well-formed action: 'cut' preview, so the refusal comes from the surface's own capability gate, not a host failure: the UI shows "The transcript preview could not be prepared.", no preview panel renders, submitEdit calls = 0, timeline stays revision 0 / 120 frames (g1-05, sha256 19fd5f35518b…)
G4(reviewer finding) A captions preview whose batch is a ripple_delete is rejected before it can be stored or appliedPASSLive, installed 0.3.4 in Chrome. The host answers the captions request with a ripple_delete batch while echoing action: "captions" — exactly the reviewer's scenario, and confirmed in the observation log ("requested action echoed as captions"). The surface refuses it: "The transcript preview could not be prepared. The host returned a transcript captions preview containing non-caption timeline commands." No preview is stored (preview:false), no apply affordance appears (apply:false, so there is no "Apply captions" over a destructive batch), submitEdit calls = 0, and the timeline keeps all 120 frames at revision 0 (g4-01, sha256 790c7c6368e6…). In-repo regression tests cover all three guard branches: captions -> ripple_delete batch, cut -> non-cut command family, and an echoed action disagreeing with the requested one
G2Transcribe starts a host transcription and polls to a succeeded receiptPASSLive. From the unavailable state the Transcribe affordance renders (g2-01, sha256 7338fa810233…); clicking it calls requestTranscription({assetId:'asset-1',language:'en'}); the surface then polls getStatus through running -> succeeded and refreshes into the real section list with status succeeded and 2 sections (g2-03, sha256 749eb0738349…)
G2bThe affordance is gated on both the port and the capability, and terminal failures stop pollingPASSLive. Host withoutrequestTranscription -> no Transcribe affordance, unavailable state otherwise unchanged (g2-04, sha256 64316bbbab00…). media.transcriptionoff -> the Transcript tab is not offered at all (g2-05, sha256 323fe6785cc6…). A terminal failed receipt -> polling stops (3 getStatus calls, not spinning), the host error surfaces, and Transcribe is re-enabled for retry (g2-06, sha256 db08790d2cb2…)
G3The poll cadence reads from an env knob with the production value as defaultPASSSource: VITE_HOST_TRANSCRIBE_POLL_MS (default 3000) and VITE_HOST_TRANSCRIBE_POLL_MAX_ATTEMPTS (default 200); the unit tests compress it via vi.stubEnv. Statically confirmed in the shipped bundle: dist/index.js inlines 3e3 / 200. Observed live at the production default — the G2 run took 6385 ms across 4 getStatus calls, i.e. the real 3 s cadence, not a test-compressed one
3The package carries its own publishable versionPASSpackage:editor-surface -> version 0.3.4, sha256 6228164a…6a0c95, identical across two runs; fresh-consumer install reports @quantfive/freecut-editor-surface@0.3.4
4TypecheckPASSnpm run check -> 0 errors across 2445 files
5LintPASSnpm run lint -> exit 0
6BuildPASSnpm run build -> built
7Changed-healthPASS9 changed files vs base; introduced dead_code=0, complexity=0, duplication=0
8Architecture gatesPASSboundaries, deps-contracts, legacy-lib-imports, deps-wrapper-health, edge-budgets
9ProvenancePASSverify:provenance -> license/notices, runtime + dev deps, asset roots
10Headless contracts (Node)PASS43/43
11Headless browser suitePASS19/19 edit-operation contracts + lifecycle HTTP/CLI import/edit/render
12Browser QA gatePASSreal system Chrome 151.0.7922.172; manifest head 33ef9525…, result PASS; digests frame.png 8206275c7f9794b6…, harness.png 2360d2cc7439d7cb…, console.log empty
13QA redactionPASScheck:qa-redaction clean + 6/6 fail-closed self-tests
14Focused in-repo tests for this diffPASSvp test run src/features/editor/host/transcript-editor.test.tsx src/features/editor/host/controller.test.ts -> 30 passed, plus the 3 inherited failures listed below (up from 27 at 63bad2b6: the 3 new mismatch regression tests)
15Full unit suiteFAIL — inherited baselinejsdom/localStorage zustand-persist crash. Stack base aca96133: 45 failed files / 584 failed / 4280 passed. This head: 45 failed files / 584 failed / 4288 passed. Same failing files, same failure count; the +8 passes are exactly this PR's 5 original tests plus the 3 new regression tests. Reproduced at the base SHA in a detached worktree; no allowlist, skip list, or config edited
16Unused exports ratchetFAIL — inherited baseline"129 findings, 119 allowlisted, 10 new, 3 stale" — output identical at base aca96133 and this head; none of the 10 is in a file this PR touches; allowlist untouched
17Unused class members ratchetFAIL — inherited baseline"83 findings, 83 allowlisted, 0 new, 2 stale" — identical at base aca96133 and this head; allowlist untouched

Rows 15–17 are the three disclosed failures, recorded as failures per
docs/qa/README.md's "baseline failures are disclosed, never hidden" rule and
each reproduced at the stack base. Prior judgments examined them and did not
treat them as blockers for any row.

Evidence artifacts. 12 screenshots (all digests distinct — checked for
duplicates to rule out a stuck or unchanged UI), the per-check results, and the
negative-control results are written with sha256 digests to a gitignored local QA
directory per docs/qa/README.md; the digests are inlined above rather than cited
by path, and the observable content of each screenshot is described inline in the
row it supports. No secrets, tokens, absolute local paths, or media bytes appear
in this report.

Scope note. The published bundle inlines import.meta.env, so the poll knob
resolves to its production default inside the packaged surface (row G3 shows the
inlined 3e3/200 and the observed 3 s live cadence). The override is effective
for source builds and tests; it is not runtime-configurable by a consumer of the
prebuilt package. That is disclosed rather than claimed otherwise.

Known non-blocking follow-up. The reviewer's approval carried one non-blocking
note: the transcription poll loop is not cancelled on unmount, so switching away
from the Transcript tab can let an in-flight request keep calling getStatus up to
its bounded attempt cap. It is generation-guarded (a stale loop cannot write state)
and bounded, so it does not affect any row above. It is left for a follow-up rather
than changing this approved head.

Overall: PASS

@codepress-dev

Copy link
Copy Markdown

👋 Hey @lightninglu10! Spawning a verification judge session to help with your request. View session

@codepress-dev

Copy link
Copy Markdown

@Terminal@lightninglu10

Dispatched by judge-verification.

This judgment is READY TO MERGE at the current head. If the PR is still a draft, transition it to ready for review now with the guarded readiness transaction: codepress-policy ready-for-review --repo . --pr 17 (or node packages/delivery-policy/dist/cli.js ready-for-review --repo . --pr 17 when the CLI is not on PATH). It re-validates current-head QA and judge evidence, reconciles the delivery-status marker, and marks the PR ready so the native reviewer can dispatch. Do not call gh pr ready directly, and do not merge; merge authorization still requires the reviewer gate.

Verification Judgment — PR #17 (local)

Verdict: ✅ READY TO MERGE

PR Head SHA:33ef952521cd0da1d885520eeac60d816084496c

Summary: The report is bound to the live PR head, the verifier captured a clean checkout, and the packed 0.3.4 surface was exercised through the real Transcript UI and caller-supplied host port. The live observations establish transcript cut preview/apply behavior, ripple deletion and capability denial, transcription start/polling/terminal handling, and the reviewer-finding regression guard. The three disclosed suite and ratchet failures reproduce at the stack base and are immaterial to the inventoried change.

Revision binding

  • Classification: SAME-SHA LATE BINDING
  • Report head:33ef952521cd0da1d885520eeac60d816084496c
  • Live PR head:33ef952521cd0da1d885520eeac60d816084496c
  • Audited checkout: clean detached checkout at 33ef952521cd0da1d885520eeac60d816084496c
  • Concrete evidence: Verifier capture: git rev-parse HEAD -> 33ef952521cd0da1d885520eeac60d816084496c; git status --porcelain -> (empty). Judge capture from a separate detached checkout: git rev-parse HEAD -> 33ef952521cd0da1d885520eeac60d816084496c; git status --porcelain -> (empty).
  • Rows carried forward:none
  • Rows reverified at live head:none
  • Rows still requiring verification:none
  • Publication timing: GitHub lists the fixing head commit at 2026-08-22T20:52:39Z and the canonical report comment at 2026-08-22T21:04:52Z; the live PR lookup returned the same full head. This establishes report/head ordering only; the captured verifier commands establish verifier checkout state.

Diff trigger inventory

SurfaceLocationCoverage
ripple_delete is accepted by the host command contract and mapped to timeline.remove, including capability denialsrc/features/editor/host/contract.ts:318-350; src/features/editor/host/controller.test.ts:367-4261
The published editor-surface declaration exposes ripple_delete and optional requestTranscriptionpackages/freecut-editor/src/index.d.ts:289-391; packages/freecut-editor/README.md:29-402
Transcript cut selects ranges, previews without mutation, applies through the host, and refuses when removal capability is offsrc/features/editor/host/transcript-editor.tsx:703-839,1096-1129; packed-surface live flowG1, G1b
A returned preview must match the requested action and command family before it is storedsrc/features/editor/host/transcript-editor.tsx:414-475,738-781; packed-surface live flowG4
Transcription request is gated, starts through the host, polls to a terminal receipt, and exposes retry after terminal failuresrc/features/editor/host/transcript-editor.tsx:850-904; packed-surface live flowG2, G2b
Poll cadence and attempt cap use environment values with production defaultssrc/features/editor/host/transcript-editor.tsx:45-75,869-876G3
The package carries a distinct publishable release slotpackages/freecut-editor/package.json:33
Deterministic, architecture, provenance, contract, focused-test, and disclosed baseline gate resultsVerification report rows 4-11 and 13-17; changed files and package artifact4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17
Browser QA gate for the packed surfaceVerification report row 12 and live system Chrome evidence12

Per-item

#Verifier saidJudgmentEvidence
1PASS✅ PASSThe diff adds ripple_delete to the supported command list and maps it to timeline.remove. The report records an applied batch reaching host.submitEdit, revision 1, and an off-capability rejection before host submission; the focused controller test reports 19/19.
2PASS✅ PASSA fresh consumer install of @quantfive/freecut-editor-surface@0.3.4 exposes ripple_delete and optional requestTranscription in the installed declaration; the consumer contract check reports 1/1.
G1PASS✅ PASSIn system Chrome against the installed 0.3.4 artifact, the real Media and Transcript surface sends action: 'cut' with the selected one-second range, makes zero submitEdit calls during preview, keeps revision 0, then applies a ripple_delete batch and observes revision 0 to 1, 120 to 90 frames, a shortened clip, and the Transcript cut applied. announcement.
G1bPASS✅ PASSWith timeline.remove disabled, the live surface rejects the otherwise well-formed cut preview, renders the preparation error, makes zero submitEdit calls, and leaves revision 0 and 120 frames unchanged.
G4PASS✅ PASSThe live captions request receives a ripple_delete batch while echoing action: "captions"; the surface rejects it before storage, shows the non-caption-command validation error, renders no preview or apply affordance, makes zero submitEdit calls, and leaves the timeline at revision 0 with 120 frames. The in-repo regression tests cover the mismatched command-family and echoed-action branches as well.
G2PASS✅ PASSThe live unavailable state renders Transcribe; clicking it calls requestTranscription({assetId:'asset-1',language:'en'}), then observes status polling through running to succeeded and refreshes the real section list to succeeded with two sections.
G2bPASS✅ PASSThe live run hides Transcribe without the optional port, removes the Transcript tab when media.transcription is off, and on a terminal failed receipt stops polling after three status calls, surfaces the host error, and re-enables retry.
G3PASS✅ PASSThe source defines VITE_HOST_TRANSCRIBE_POLL_MS and VITE_HOST_TRANSCRIBE_POLL_MAX_ATTEMPTS with defaults 3000 and 200; the shipped bundle contains the corresponding values, and the live production-default run took about 6.4 seconds across four status calls.
3PASS✅ PASSThe package manifest and fresh artifact both report version 0.3.4; the package tarball was byte-identical across two consecutive builds and installed successfully in the consumer.
4PASS✅ PASSnpm run check reported zero errors across 2445 files.
5PASS✅ PASSnpm run lint exited 0.
6PASS✅ PASSnpm run build completed successfully.
7PASS✅ PASSThe changed-health scan reported dead_code=0, complexity=0, and duplication=0.
8PASS✅ PASSBoundary, dependency-contract, legacy-import, wrapper-health, and edge-budget gates all passed.
9PASS✅ PASSProvenance verification passed for licenses and notices, runtime and development dependencies, and asset roots.
10PASS✅ PASSHeadless Node contracts reported 43/43.
11PASS✅ PASSThe headless browser suite reported 19/19 edit-operation and lifecycle checks.
12PASS✅ PASS (FORM CAVEAT)Real system Chrome 151 browser QA reported PASS with a head-bound manifest, distinct artifact digests, and an empty console log. Advisory form caveat: the referenced screenshot files are gitignored local artifacts rather than visual evidence published at a durable URL; the inline runtime observations remain concrete.
13PASS✅ PASSQA redaction passed, including six fail-closed self-tests.
14PASS✅ PASSThe focused transcript-editor and controller run reported 30 passing tests; the report separately identifies the three inherited teardown failures.
15FAIL — inherited baseline✅ WAIVEDThe full-suite failure is the same 45-file and 584-test jsdom/localStorage zustand-persist crash at stack base aca961335d9856fe6e5059950646f6ca0bbf9d2a and this head. The changed-surface tests and live flows pass, and the unchanged failure is unrelated to the inventoried behavior.
16FAIL — inherited baseline✅ WAIVEDThe unused-export ratchet output is identical at the stack base and head, with the allowlist untouched and none of the new findings in a changed file. It does not indicate a new export defect in this PR.
17FAIL — inherited baseline✅ WAIVEDThe unused-class-member ratchet output is identical at the stack base and head, with no new findings and the allowlist untouched. It does not indicate a new class-member defect in this PR.

Overall status check

  • Verifier said: PASS
  • Result: READY TO MERGE

What stood up

  • Same-SHA binding is supported by explicit verifier git rev-parse HEAD and empty git status --porcelain capture, plus a separate clean detached audit checkout.
  • The packed-artifact run directly exercised the real Transcript UI, host request port, polling loop, capability gates, preview/apply boundary, and resulting timeline state.
  • The negative control distinguishes the changed 0.3.4 surface from the stack-base 0.3.3 surface, while the inherited failures are disclosed and reproduced at the stack base rather than hidden.

@lightninglu10
lightninglu10 merged commit f0f5639 into codepress-mainAug 22, 2026
3 of 4 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@lightninglu10