SkillsSkill for Claude

Grant report evidence sheet

Give Claude the phone videos your field staff shot during one grant period and the deliverables in the grant agreement (a training held, supplies handed out, a facility built, a community meeting), and it returns an evidence sheet: one row per checked moment where the footage shows a deliverable or a staff member explains it, with the source file, the shot date from the file's metadata, the time, a frame or the staff member's words from a transcript, and an empty image consent column. Claude prices the indexing against your Vivu plan, indexes the clips in a private Vivu project, runs a visual and a spoken search per deliverable, and checks every window against frames or the transcript before it becomes a row. Field reports say a training happened; funders want to see it, and clips named only by date do not say which one shows what.

Maintained by Vivu. Updated 2026-10-16.

Download

grant-report-evidence-sheet.zip

11 KB. Unzips to grant-report-evidence-sheet/SKILL.md. Upload the zip as it is in the Claude app, or unzip it into your skills folder for Claude Code.

SHA-256 e65e59f9517f5e8c7644820f7be6da0c6bea542f141148b30d1e4d7ecd40e183

At a glance

What the Grant report evidence sheet skill does, where it runs, what it needs, and when it asks
Looks forMoments that show a deliverable happening (people being trained, supplies changing hands, a finished well in use) and stretches where staff explain the activity. Crowd scenes are where Vivu is least reliable, so every window is checked against the source video before it reaches the sheet: a contact sheet and a full frame for visual rows, the transcript for spoken ones.
Runs onClaude Code on your computer (terminal or the Code tab of Claude Desktop): it needs a shell with ffmpeg and the field clips as local files. No residential IP is needed because nothing is downloaded from YouTube, and nothing is scheduled. Creating the appendix as a shared document uses the Google Drive or Notion connector.
Needs
  • The Vivu connector with write access, to create a private project, open its upload page and search
  • A shell with ffmpeg and ffprobe, to measure minutes, read shot dates and make contact sheets and frames
  • The field clips as local video files in one folder, because frames and dates come from them
  • The deliverables from the grant agreement, because each becomes a visual and a spoken search
  • A local transcript for clips with speech, because quotes come from it; without one, spoken rows stay candidates
  • Your organization's image consent records, to fill the image consent column before any frame goes into a report
  • A browser that can open the Vivu upload page, since the connector has no direct upload tool
  • The Google Drive or Notion connector, only if you want the appendix as a shared document
Your Vivu planIndexing uses Vivu index minutes for the clips in the grant period, and each deliverable uses two precise searches at 5 credits each. The skill measures the minutes with ffprobe, reads your allowance with vivu_get_usage and shows the cost before anything is uploaded. Forty clips of about a minute and a half fit the Premium plan ($30 a month, 180 index minutes), not the Free plan with 20 index minutes a month.
Asks you firstIt asks you to confirm the organization shot the footage and that image consent covers uploading it to a third party service, then asks before indexing (deliverables, queries and clip list), before uploading (minutes and credit estimate against your plan), before writing the full sheet (sample rows and field mapping), and before creating a shared document (the destination and the full rendered appendix).

The skill does its video work through the Vivu connector. If the connector is not in your Claude yet, add it first; the skill checks that it is connected before it does anything else.

Before you run it

  • Index only footage your organization shot or has rights to, and only clips whose image consent covers uploading to a third party cloud service.
  • Recognizing crowd scenes such as trainings, distributions and meetings is weak in Vivu; search results are candidates that the skill checks one by one against frames, and background crowds and look alike scenes are rejected and counted.
  • The reason text can describe a scene that is only in the background or paraphrase what was said, so rows come from frames and transcripts only.
  • Spoken search was tested only on English speech; for other languages it is untested, so quotes rely on your local transcript.
  • An empty or short result does not prove a deliverable was not filmed; the skill checks the clips from the activity dates before calling it a gap.
  • Rows whose frames show a child are marked minor in frame and stay out of the report without recorded guardian consent.
  • Creating a shared document acts as you; the appendix is shown in full and created only after you approve it.
  • Claude in Chrome uploads at most 10 MB per call; larger clips are added in the Vivu web app, never split or recompressed.
  • Clips stay in your Vivu project until you delete them, and the project is created private because the default is visible to the whole organization.
  • No face or voice recognition, no naming of beneficiaries, and no judging of the program's results.

Start it

Once the skill is installed, ask for the task in your own words. Naming the skill is the most reliable way to have Claude use it. For example:

Our field team's videos for the Q1 grant period are in CLIPS_FOLDER, named only by date. The grant deliverables were farmer training sessions, food parcel distributions and two new wells. Find the clips that show each one and where staff explain it, and give me an evidence sheet I can pick appendix frames from.

In Claude Code you can also type /grant-report-evidence-sheet. Claude asks for anything the request leaves out, most important first.

What is inside

  1. When to use
  2. Working principles
  3. What you need before starting
  4. Inputs to collect
  5. Files and state
  6. Step 1: Check the Vivu connector and the setup
  7. Step 2: Confirm rights, read shot dates and write the deliverables
  8. Step 3: Price the indexing and get approval
  9. Step 4: Upload and index
  10. Step 5: Search each deliverable and check every window
  11. Step 6: Assemble the sheet and confirm the sample
  12. Step 7: Create the appendix document (optional)
  13. Compliance
  14. Known failure modes

The full skill

This is grant-report-evidence-sheet/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: grant-report-evidence-sheet
description: "Turn a grant period's field phone videos into a checked evidence sheet with Vivu: per deliverable, file, shot date, time, frame and staff quote. Use when a funder report needs proof."
---

Grant report evidence sheet from field footage

This skill takes the phone videos field staff shot during one grant period (typically 30 to 50 clips of 30 seconds to 3 minutes, named only by date, such as VID_20260312_101533.mp4) and the four to six deliverables in the grant agreement (a training session held, supplies handed out, a facility built, a community meeting), and returns evidence_sheet.csv: one row per checked moment where the footage shows a deliverable happening or a staff member explains it. Each row has the deliverable, the source file, the shot date read from the file's metadata, the start and end time, a frame path, a description written from the frame, the staff member's words from a local transcript, and an empty image consent column. Claude prices the indexing against the user's Vivu plan, uploads the clips to a private Vivu project, runs one visual search and one spoken search per deliverable, checks every result window against frames or the transcript, and only then writes the sheet. The program manager picks frames from it for the report appendix.

The value is in what the field reports leave out. A field report says "training completed, 32 participants"; the funder wants to see what that looked like, and that only exists in the picture: a row of people facing a trainer, boxes going into car trunks, a finished well with water coming out. The file names say nothing about which activity a clip shows, and most clips have no transcript to search. Vivu finds candidate moments by what is on screen and what is said. Crowd scenes are where it is least reliable: in our test run it returned an interview as a distribution because a queue was visible far behind the speakers, called a training hall a community meeting, and missed workshop stretches where nobody stood at the front. So every window is checked against frames before it becomes a row, and rejected windows are counted.

When to use

Use when a program or grants manager says "find footage for each deliverable in the grant report", "which of these field videos show the training and the distribution", "pull frames for the funder report appendix from our phone videos", or "build an evidence table from this quarter's field clips". For one question about one clip, search Vivu directly. For sponsor deliverables at an event (logos on stage, sponsor mentions), use an event sponsor log skill instead; for checking which shots a new shoot still needs, use a shot list coverage skill. This skill does not judge whether a program worked, count beneficiaries or identify anyone in the footage.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. A moment becomes a row only after its frames show the deliverable (visual rows) or the transcript has the words (spoken rows). Vivu's results are candidates until then; rejected candidates are counted and kept in rejected.csv.
  3. Stop and tell the user when a required capability, consent or file is missing (no ffmpeg, no write access in Vivu, clips the organization did not shoot). Do not guess around it.
  4. Ask the user before anything that is expensive to redo or that acts on their behalf: the indexing cost before upload, the sample rows before the full sheet, and any document created in a shared drive or Notion.
  5. Describe what the footage shows and says. Never rate the program, and never name or identify beneficiaries; the sheet describes activities, not people.

What you need before starting

Check each item at the start of the run and tell the user plainly what is missing.

Requirement Why How to check
Vivu connector with write access create a private project, open its upload page, search vivu_get_account shows can_create_projects: true (tool names may carry a server prefix). A write call failing with "has not granted vivu.write" means the connection is read only; the user reconnects Vivu and allows write access
A shell with ffmpeg and ffprobe on the machine that holds the clips measure minutes, read shot dates, make contact sheets and frames ffmpeg -version and ffprobe -version
The field clips as local video files in one folder frames and dates come from the local files; Vivu has no export tool ls CLIPS_FOLDER and show the user the file count and three names
The deliverables from the grant agreement each one becomes a visual search and a spoken search the user pastes the list or points to the agreement
A local transcript for clips with speech (a speech to text tool such as whisper, or transcripts the team already has) quotes come from it, never from Vivu's reason text whisper --help, or ls CLIPS_FOLDER for .vtt, .srt or .txt files; without one, spoken rows stay candidates
The organization's image consent records the image_consent column is filled from them before any frame goes into the report the user names where they are kept
A browser that can open the Vivu upload page the connector has no direct upload tool the user opens the link, or Claude in Chrome is connected
Google Drive or Notion connector, only if the appendix should be created as a shared document Step 7 open the folder or parent page the user names

The skill needs a shell and local files, so it runs in Claude Code on the user's computer (terminal or the Code tab of Claude Desktop). It downloads nothing from YouTube, so no residential IP is needed, and nothing is scheduled.

Inputs to collect

Ask for anything missing, most important first.

  1. The deliverables, four to six, each with a key and one line of what a funder would expect to see (for example training_session: a training or workshop under way, with participants and a trainer). Required.
  2. The clips folder (CLIPS_FOLDER) and the grant period dates. Required. Clips outside the period are left out.
  3. Whether the organization shot all of these clips itself. Required; see Compliance.
  4. Where image consent records are kept. Default: the image_consent column stays empty for the user to fill.
  5. Whether to also create the appendix as a Google Doc or Notion page. Default: no, evidence_sheet.csv and report_appendix.md only.
  6. The Vivu project name. Default: "Grant GRANT_NAME evidence PERIOD", private, where GRANT_NAME is the grant's short name and PERIOD the reporting period.

Files and state

Keep everything in one working folder next to the clips:

grant-evidence/
  deliverables.json   deliverable key, what counts, visual query, spoken query
  clips.csv           file, shot_date, date_source, minutes, in period, vivu video id
  results/            raw search results, one JSON file per search
  sheets/             0.5 second contact sheets of each window
  frames/             one full frame per verified visual row
  transcripts/        local transcripts, one per clip with speech
  evidence_sheet.csv  verified rows
  rejected.csv        windows that failed the check, with the reason
  coverage.md         per deliverable: verified visual rows, verified spoken rows, gaps
  report_appendix.md  the appendix draft built from the sheet
  state.json          uploaded files, searches run with job ids, every window with its verdict, rows written, documents created

state.json is updated after every step. A rerun reads it first: files already uploaded are not uploaded again, searches already run are not rerun, checked windows keep their verdicts, and a shared document already created is never created twice, so an interrupted run resumes where it stopped and no moment is written twice.

Step 1: Check the Vivu connector and the setup

Goal: every row of What you need is confirmed before anything is uploaded.

  1. Call vivu_get_account. If the tool is missing, tell the user to add the Vivu connector in Claude (https://mcp.vivu.ai/mcp) and stop. If can_create_projects is not true, or a write call later fails with "has not granted vivu.write", ask the user to reconnect Vivu with write access and stop until they have.
  2. Run ffmpeg -version and ffprobe -version. List CLIPS_FOLDER and show the file count and three names. Check for a speech to text tool or existing transcripts.
  3. If a shared document is wanted, open the Drive folder or Notion parent page the user names.
  4. Create the working folders; ffmpeg does not create an output folder:
mkdir -p grant-evidence/results grant-evidence/sheets grant-evidence/frames grant-evidence/transcripts

Run every later command from inside grant-evidence/ (cd grant-evidence), with CLIP_FILE as the path to a clip from there.

Done when vivu_get_account shows can_create_projects: true, ffmpeg and ffprobe print versions, the clip count is confirmed with the user, and the working folders exist.

Step 2: Confirm rights, read shot dates and write the deliverables

Goal: deliverables.json and clips.csv, with only the organization's own clips from the grant period.

  1. Ask the questions in Compliance items 1 and 2 before anything else in this step.
  2. Read each clip's shot date from its metadata. Phones write a creation_time tag; files that went through WhatsApp, a messaging app or an editor often lose it:
ffprobe -v error -show_entries format_tags=creation_time -of default=nw=1:nk=1 CLIP_FILE

An empty answer means the tag is missing. Then take the date from a YYYYMMDD pattern in the file name and set date_source to file_name; with neither, write UNCERTAIN and ask the user. Leave out clips dated outside the grant period, and tell the user how many. 3. Write each deliverable as two queries. The visual query describes what a camera would see, not the program's name for it: "a group of adults sit facing one person who stands at the front and teaches", not "capacity building workshop". The spoken query describes what a staff member says about it. Use this shape:

Field Query template Mode maximum_results
KEY_visual VISIBLE_SCENE precise 40
KEY_spoken a staff member or volunteer explains to the camera STATEMENT precise 40

VISIBLE_SCENE is the deliverable in plain words a camera would show (for example "boxes and bags of food are handed out or loaded into cars by volunteers"), STATEMENT what staff would say ("what the training is about and who is taking part"). All searches are precise because rows need time ranges; a fast search only returns whole files with an empty reason, and field clips are short enough that there is no file choice left for fast to make. maximum_results is 40 because one deliverable rarely appears in more than a dozen windows across a grant period's clips; it is also the ceiling on what comes back, so a list that stops at exactly 40 means the cap was hit: raise it and rerun. 4. Show the deliverables, the queries and clips.csv, and wait for a yes.

In our test run, clips that had been re-encoded had no creation_time, so their dates came from the file name. The rights and consent questions were not exercised in our test run, which used public Creative Commons footage.

Done when the user has confirmed rights and approved deliverables.json and clips.csv.

Step 3: Price the indexing and get approval

Goal: the user sees the cost before anything is uploaded.

  1. Measure each clip and sum the minutes:
ffprobe -v error -show_entries format=duration -of csv=p=0 CLIP_FILE
  1. Call vivu_get_usage for the plan and what remains this month.
  2. Estimate search credits: two precise searches per deliverable plus one rewording each for the visual searches in case the first page is not clean. A precise search uses 5 credits in total. Label the total as an estimate.
  3. Show one table and wait for approval:
This grant period Remaining on the plan
Index minutes measured sum from vivu_get_usage
Search credits estimate from vivu_get_usage

For reference, the Free plan has 20 index minutes a month and 50 search credits a month; Premium is $30 a month with 180 index minutes and 500 search credits. Forty clips of about a minute and a half fit Premium, not Free. If the period does not fit, offer these levers in order: index only the clips from the dates when deliverable activities took place (the activity log or field reports usually say), split the period across months, and only then a larger plan. Never drop a clip the user asked for without saying so.

vivu_get_usage on our test account returned no remaining allowance, so the comparison against a real plan and the user's approval were not exercised in our test run.

Done when the user has approved the minutes and the credit estimate.

Step 4: Upload and index

Goal: every clip in clips.csv is ready in a private Vivu project.

  1. Call vivu_list_projects and reuse the project named in the inputs if it exists. Otherwise call vivu_create_project with that name and visibility "private". Field footage shows beneficiaries, sometimes children; the default visibility is the whole organization.
  2. Call vivu_open_upload_page with the project ID right before the upload. The link expires in 180 seconds and is a sign in link, so never paste it into a message or file. Give it to the user to open in their own browser and choose the files from clips.csv, or attach the files with a browser tool that can upload local files. Claude in Chrome accepts at most 10 MB per upload call; larger clips are added by the user in the Vivu web app. Never split or recompress a clip to fit.
  3. Poll vivu_list_videos about every 30 seconds until every file shows ready. Match each video back to clips.csv by file name; Vivu turns spaces and punctuation in names into "_", so compare names with those characters replaced. Record the video IDs in clips.csv and state.json.

In our test run the 12 clips went to queued, then indexed one or two at a time, and were all ready 9.6 minutes after the upload started. The user's own browser upload was not exercised in our test run.

Done when vivu_list_videos shows every file in clips.csv as ready.

Step 5: Search each deliverable and check every window

Goal: for each deliverable, a list of checked moments with rejected windows counted.

Run each query in deliverables.json with vivu_search_videos (project_id, query, mode "precise", maximum_results 40). It returns a job ID. Call vivu_get_search_results until complete is true; each status call can wait up to 45 seconds, so a pending search is not a stalled one. Save each completed result as results/FIELD.json, where FIELD is the query's field name. Show the result page link in the live reply only; it expires after four hours, so it never goes into the sheet, the appendix or any file.

Vivu returns a time range that contains the moment, not an exact frame, and the reason text describes what Vivu thinks it saw; it can describe a scene that is only in the background. Check every window:

  1. Visual queries: make a contact sheet of the window (START is start_ms / 1000, DURATION is (end_ms - start_ms) / 1000, CLIP is the clip file name without its extension). For windows up to 30 seconds use two frames a second (RATE 2); for longer windows use one frame every two seconds (RATE 0.5). ROWS is DURATION x RATE / 10 rounded up:
ffmpeg -v error -ss START -t DURATION -i CLIP_FILE -vf "fps=RATE,scale=240:-2,tile=10xROWS" -frames:v 1 sheets/FIELD_CLIP_START.png

Look at the sheet. The window is real only if a cell shows the deliverable itself as the subject of the shot: people being trained, supplies changing hands, the finished facility. For a distribution, at least one cell must show supplies being handed over, carried or loaded, not people standing still beside boxes for a photo. Reject the window when the activity is only in the far background of an interview, when the only supplies are in a posed group shot, when the facility is out of frame, or when the scene is a different deliverable. Apply the same rule to every window of a deliverable, and write it into deliverables.json so a rerun judges the same way. When a cell shows it, extract one full frame at that cell's time (SECONDS is START plus the cell's index divided by RATE; cells count from 0, left to right, top to bottom) and look at it before writing the row:

ffmpeg -v error -ss SECONDS -i CLIP_FILE -frames:v 1 -q:v 3 frames/FIELD_CLIP_SECONDS.png

Keep the quotes around the filter; some shells treat the comma list as a pattern otherwise. 2. Spoken queries: read the transcript lines inside the window. The window is real only if the staff member says it there. Quotes come from the transcript, never from the reason text, which paraphrases. When a clip has no transcript, read vivu_get_video_summary with include_segments, start_ms and end_ms around the window as a second signal, keep the row as a candidate with quote NOT VERIFIED, and tell the user to listen to that stretch. Spoken search was only tested on English speech; for clips in other languages it is untested, so rely on the local transcript and treat Vivu's spoken windows as candidates. 3. While looking at frames, mark every row whose frames show a child as minor in frame. 4. When the same window passes for two deliverables (a nutrition group can look like a training and a meeting), keep both rows and say so in notes; the program manager decides which deliverable it supports. Do the same for volunteers packing or passing supplies in a warehouse: keep the row, note "packing, not a hand off", and let the program manager decide whether it counts as a distribution. 5. Rejected windows go into rejected.csv with the reason; they are counted, not dropped silently. 6. A missing deliverable is not proof it did not happen. Vivu's results stop at what it ranks as matching, and wide windows hide shorter moments. For every deliverable with fewer verified rows than the user expects, make a whole clip contact sheet (RATE 0.5) of the clips from the dates the activity took place and look for it there.

These wordings ran in our test; adapt the scene and statement to the user's deliverables and keep the shape:

Field Query Mode maximum_results
training_visual a row or group of adults stand or sit and watch one person in front of them who talks, points or shows something with their hands, indoors at tables or in rows of chairs, or outdoors in a field precise 40
distribution_visual volunteers hand boxes or bags to people or load them into car trunks; the supplies are being moved and are the subject of the shot, not a crowd behind someone talking or a group posing next to boxes precise 40
facility_visual a newly built facility such as a water well, hand pump, tank, pond or building, shown finished and being used precise 40
meeting_visual a community meeting: villagers or residents sit together in a circle or rows while someone speaks to the group precise 40
training_spoken a staff member or organizer explains to the camera what the training or workshop is about and who is taking part precise 40
distribution_spoken a staff member or volunteer explains to the camera the food or supplies being given out and who they are for precise 40

The meeting query is the least reliable: in our test run it returned 3 windows, 1 of them false (a training hall), and its real windows were the same moments the training query found. Treat meeting rows as candidates the program manager confirms.

Why this chain: the visual query finds the clips and windows where the deliverable is on screen, the contact sheet and full frame turn each window into a checked moment and separate the activity from a crowd in the background, and the spoken query adds what staff said about it, checked against the transcript. The flip runs both ways: a clip where staff say "this is the training" gets checked for a training in the frame, and a training on screen gets checked for a staff explanation.

Worked example from our test run

In our test run we used 12 public clips, 19.82 minutes in total, cut from Creative Commons videos of nonprofit projects (health worker workshops, a field demonstration for women farmers, a hall training, food distributions, new wells filmed on phones, a women's nutrition group) and renamed to phone style date names. Several are edited news pieces or NGO films, not raw field clips, so vertical shaky phone footage was only partly represented. Before searching we wrote down from contact sheets which stretches of which clips showed each deliverable, plus distractors such as a posed group standing behind an interviewee, group photos and people carrying buckets.

The first training wording returned 6 windows: 6 real, 0 false, but 4 training stretches were missed, including the outdoor field demonstration and seated classroom rows. After 1 rewording on the same corpus, describing only what a camera sees, the training query returned 8 windows: 8 real, 0 false, with 3 stretches still missed (table group work where nobody stood at the front, and seated rows in a health worker training). One window covered 117 seconds of a 120 second clip, so the contact sheet, not the window, sets the row's time. The first distribution wording ("supplies being handed out: people line up or gather at a table or car where volunteers hand them boxes, bags or packages") returned 5 windows: 3 real and 2 false, and 2 stretches were missed. Both false windows opened on a group posing still beside boxes, then cut to an interview with the distribution crowd far behind the speakers; the moments when boxes went into car trunks fell just outside them. After 1 rewording on the same corpus, naming the hand off and ruling out posed groups and background crowds, the distribution query returned 5 windows: 5 real, 0 false, with 1 stretch (boxes handed into a car trunk) still missed. Two of those 5 were warehouse volunteers bagging food and passing boxes, which we had marked as borderline before searching and counted as real; a program that counts only hand offs to recipients would reject them. The facility query returned 5 windows: 4 real, 1 false where the well never appeared in frame. The meeting query returned 3 windows: 2 real (the same nutrition group the training query found) and 1 false, the training hall. A control query for solar panels, which no clip shows, returned 0 results.

Spoken explanations were found by meaning: the distribution query returned 3 windows, 3 real against the subtitles; the training query returned 2 real and 1 unjudged on a clip with no transcript, kept as a candidate. Quotes in the sheet came from subtitles, used in our test run as the stand in for a local transcript.

Done when every window of every query has a verdict in state.json and the user has seen the real, rejected and candidate counts per deliverable.

Step 6: Assemble the sheet and confirm the sample

Goal: one table the program manager uses to pick appendix frames.

  1. Build one row per verified moment. Narrow start and end to the cells or transcript lines that show it, not the whole Vivu window:
deliverable,evidence_type,source_file,shot_date,date_source,start_mmss,end_mmss,frame_path,scene_description,spoken_summary,quote,quote_source,status,image_consent,notes
supply_distribution,visual,VID_20260321_100125.mp4,2026-03-21,file_name,00:42,00:46,frames/distribution_visual_VID_20260321_100125_43.png,"Volunteers in high visibility vests load a box of food into an open car trunk",,,,verified,,
  1. Field mapping:
Field Source If unavailable
deliverable deliverables.json none
evidence_type visual or spoken, from the query none
source_file the original file name from clips.csv none
shot_date, date_source creation_time from ffprobe, else the date in the file name UNCERTAIN
start_mmss, end_mmss the contact sheet cells or transcript lines inside the window the Vivu window, marked UNCERTAIN
frame_path the full frame the row was checked on blank for spoken rows
scene_description Claude's description of the full frame (inferred) none
spoken_summary Claude's one line summary of what was said (inferred) blank for visual rows
quote the transcript lines, word for word NOT VERIFIED
quote_source the local transcript or subtitles none
status verified candidate when it could not be checked
image_consent left empty for the user to fill from consent records blank
notes minor in frame, overlaps with another deliverable blank
  1. Show two or three sample rows and the mapping and wait for a yes before writing the full sheet. Say which fields are inferred: scene_description and spoken_summary are Claude's readings; if one is wrong, a background crowd can read as the activity.
  2. Write evidence_sheet.csv, rejected.csv and coverage.md, and give the user the counts: rows per deliverable, windows rejected and why, candidates waiting for a listen, rows marked minor in frame, and deliverables with no verified row.
  3. Draft report_appendix.md from the verified rows: one section per deliverable with file name, shot date, time, description, frame path or quote. Leave frames out of rows whose image_consent is empty.

In our test run the sheet, rejected.csv, coverage.md and the appendix draft were built from the checked windows; the user's approval of the sample rows was not exercised in our test run.

Done when evidence_sheet.csv exists with one row per verified moment and the user has approved the sample rows.

Step 7: Create the appendix document (optional)

Goal: the appendix as a Google Doc or Notion page in the place the user chose.

  1. Only if the user asked for it in the inputs. Render it from evidence_sheet.csv: one section per deliverable, one entry per row with the source file, shot date, time, frame and description or quote. Use the file name and time, never a Vivu result page link (it expires after four hours). Leave out every row whose image_consent is empty or no, and every row marked minor in frame without guardian consent.
  2. Creating the document acts as the user and may share beneficiary images. Name the destination, show the full rendered appendix, and wait for an explicit yes. Record the document in state.json so a rerun never creates it twice.

Step 7 was not exercised in our test run: the appendix was rendered to report_appendix.md and no Drive or Notion connector was called.

Done when the approved document exists and is recorded in state.json, or the user chose the local files only.

Compliance

  1. Index only footage the organization shot itself or has written rights to use. Ask before Step 2. Footage downloaded from social media or sent by partners without permission stays out.
  2. People in the footage are beneficiaries and community members. Ask whether the organization's image consent covers uploading their footage to a third party cloud service for analysis; leave out clips that are not covered. The image_consent column stays empty until the user fills it from the organization's records, and no frame goes into a report or shared document without consent recorded.
  3. Minors: mark every row whose frames show a child as minor in frame. Those frames go into a report only with recorded guardian consent; without it, they stay out.
  4. No face, voice or identity recognition. The sheet describes activities; it never names or identifies beneficiaries.
  5. The clips stay in the user's Vivu project until the user deletes them. Create the project as private (the default is visible to the whole organization). The skill never calls vivu_delete_video or vivu_delete_project unless the user asks, and confirms first.
  6. The sheet records what the footage shows and says. It never rates the program's results or the people in it.

Known failure modes

Symptom Cause Fix
(observed) a window opens on a group posing beside boxes, then is an interview with the activity only far in the background; in our test run 2 of 5 windows from the first distribution wording were like this, one with the reason "People line up along the outdoor hallway where volunteers at tables hand out supplies and packages." visual search reads the whole scene coarsely, including posed shots and what is behind the subject judge every window from the contact sheet and reject it unless a cell shows the supplies moving; word the query as the hand off itself and exclude posed groups and background crowds (after 1 rewording our distribution query returned 0 false)
(observed) training stretches on the contact sheets are never returned; in our test run the first wording missed 4, and after 1 rewording 3 were still missed table group work with nobody standing at the front, and seated rows, do not match a teacher and audience picture write the query as what a camera sees, and make whole clip contact sheets of the clips from training days before reporting a gap
(observed) a window covers almost the whole clip; in our test run one training window was 117 seconds precise returns a range that contains the moment, sometimes the whole clip narrow the row's time to the contact sheet cells that show it
(observed) a training is returned as a community meeting; in our test run the reason said "Villagers sit together on the floor facing the front as a man stands at the table and addresses the community meeting." seated groups facing a speaker look alike across deliverables check the frame for the banner, setting and activity; record overlaps in notes and let the program manager decide
(observed) a facility window does not show the facility; in our test run 1 of 5 facility windows never had the well in frame shaky phone footage pans away from the structure require a cell where the finished structure itself is visible
(observed) a clip with speech has no transcript; in our test run 1 spoken training window stayed unjudged the clip had no subtitles and no local transcript keep it as a candidate with quote NOT VERIFIED, read the summary segments, and ask the user to listen
(observed) a clip has no shot date in its metadata files sent through messaging apps or re-encoded lose the creation_time tag take the date from the file name and set date_source to file_name; with neither, write UNCERTAIN
a quote in the reason text does not match the recording the reason is a paraphrase, not a transcript copy quotes from the transcript only
a list stops at exactly maximum_results the cap cut the list short raise maximum_results and rerun that query
a deliverable has no verified rows an empty result does not prove the footage has no such moment make whole clip contact sheets of the clips from the activity dates before telling the user it is missing
"has not granted vivu.write" Vivu connected read only the user reconnects Vivu with write access
upload page asks to sign in or shows an error the one time upload link expires after 180 seconds request a new link right before opening it
a file is rejected by the browser upload tool Claude in Chrome takes at most 10 MB per upload call the user adds that file in the Vivu web app; never split or recompress it
a result's file name does not match clips.csv Vivu replaced spaces or punctuation in the name compare names with those characters replaced by "_"

Connect Vivu, then add the skill.

The skill runs through the Vivu connector. Add it to Claude from the connector directory, then install the skill.