SkillsSkill for Claude

Site walk delay report

Give Claude this week's site walk videos and the job schedule. Claude pulls the activities due by the walk date, indexes the walk in a private Vivu project for that date, finds where the walker names each room (or reads the sign that opens each room's clip), looks at full resolution frames of each confirmed room to name its construction stage, and in a full run also searches for three stages (bare studs, drywall hung but not finished, ceiling grid with no tiles) to point at moments worth checking. It writes a progress check CSV and a delay list by subcontractor. The stage is only visible in the footage, and a stage counts only where a sign, a transcript or you tie that stretch to a schedule room, so a room nothing confirms stays NOT SEEN. Vivu's stage search often returns a neighboring stage, so every result is a candidate until the frames confirm it, and a subcontractor only hears about a delay that a checked frame shows.

Maintained by Vivu. Updated 2026-09-28.

Download

site-walk-delay-report.zip

14 KB. Unzips to site-walk-delay-report/SKILL.md. Upload the zip as it is in the Claude app, or unzip it into your skills folder for Claude Code.

SHA-256 6e86374b94100729733a8207dc3c863d8cdaeb2985753e83694f1664b1922f90

At a glance

What the Site walk delay report skill does, where it runs, what it needs, and when it asks
Looks forRooms that show an earlier construction stage than the schedule expects: studs you can see through where drywall should hang, bare screw rows where walls should be finished, T-bars with no tiles. Schedules and daily reports cannot show the room itself; the walk video can. Every Vivu result is checked against frames from your original video before it reaches the report.
Runs onClaude Code on your computer (terminal or the Code tab of Claude Desktop), because it needs a shell with ffmpeg and ffprobe and the walk videos on local disk. No residential IP is needed and nothing is scheduled: you run it once per walk.
Needs
  • The Vivu connector with write access, to create a private project per walk date, open its upload page, search and read summaries.
  • A shell with ffmpeg and ffprobe on the machine that holds the walk videos, for durations, frame checks, contact sheets and cutting stretches out.
  • This week's walk videos as local files, with 360 footage exported flat, because Vivu indexes your uploads and frames are cut from your copy.
  • The schedule as a CSV export, or a Todoist or Linear connector with read access, to list the activities due by the walk date.
  • A browser you can open the upload page in, or a browser tool that can attach local files.
  • For walks where rooms are named out loud, a transcript of the walk, or your time to play each named moment and confirm the room.
  • A Slack connector with access to each subcontractor's channel, only if you want the messages posted; frames are attached only when it can upload files.
Your Vivu planIndex minutes equal the total length of the walk files you upload. A continuous walk uses one precise room search, and a full run adds up to three precise stage searches; a precise search uses 5 credits in total. That is an estimated 20 credits a walk for a full run and an estimated 5 credits for a rooms only run. Four weekly full runs come to an estimated 80 credits a month, more than the Free plan's 50 search credits a month. The skill checks whether rooms can be tied before any spend, prices the walk against your plan with vivu_get_usage and waits for your yes before uploading.
Asks you firstBefore any spend (whether rooms were named or signed on camera, full or rooms only run, the cost against your plan and the compliance points), before the report is built (the activity mapping, each spoken room name you confirm by playing it when there is no transcript, the name mapping and a sample row), and before any subcontractor gets a Slack message (the destination, a fully rendered sample and every frame that would be attached).

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

  • Vivu's construction stage search is a candidate finder, not a judge: in our test run 6 of 8, 4 of 10 and 3 of 6 returned windows showed a different stage, so the skill checks every result on frames, one by one.
  • The stage searches only point at moments: in our test run they added no judged row that a direct look at the named rooms missed, so the skill offers a rooms only run without them.
  • A room is tied to footage only through a door or paper sign read from a frame, or a spoken room name checked against a transcript or confirmed by you; room numbers in Vivu's reason text or summaries are never used on their own.
  • NOT SEEN means the walk did not show that room and stage clearly enough; it never becomes BEHIND, and continuous walks with few rooms named on camera produce many NOT SEEN rows.
  • Door sign reading and filming a clip per room were not exercised in our test run, because the public walks we used are continuous and show no signs.
  • Search wording was tuned on spherical camera walks of two clinic build-outs; ordinary phone footage, other building types and other stages were not tested.
  • Walks catch workers, and occupied sites can catch patients or children: check the site's filming rules, identify no one, and leave children out unless a guardian agreed.
  • Slack messages to subcontractors post as you, and only after you approve the destination, a rendered sample and every frame to be attached.
  • Uploaded walks stay in your Vivu project for that walk date until you delete them; the skill creates each project as private.
  • The upload link expires in 180 seconds, and Claude in Chrome uploads at most 10 MB per call, so larger walk files go through your own browser or the Vivu web app.

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:

Check this week's site walk in ~/Site/walk_2026-09-22 against schedule.csv and give me the delay list by subcontractor before anything goes to Slack.

In Claude Code you can also type /site-walk-delay-report. 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: Build the expected table from the schedule
  8. Step 3: Collect the walk videos and check the rooms
  9. Step 4: Choose the run, size it and get approval
  10. Step 5: Create a private project for this walk date and upload
  11. Step 6: Search the stages and check every candidate on frames (full run only)
  12. Step 7: Tie what was seen to rooms
  13. Step 8: Build progresscheck.csv and delays.md
  14. Step 9: Message subcontractors after approval (optional)
  15. Compliance
  16. Known failure modes

The full skill

This is site-walk-delay-report/SKILL.md from the download, as Claude reads it: the frontmatter first, then the instructions.

---
name: site-walk-delay-report
description: "Compare site walk videos with the schedule using Vivu and get a delay list per subcontractor, each BEHIND backed by a frame Claude checked. Use after weekly walks in framing, drywall or ceiling work."
---

Site walk delay report with Vivu

This skill takes this week's site walk videos (phone or 360 camera footage on local disk) and the job schedule (a CSV export, or a Todoist or Linear project) and produces a delay list. Claude pulls the activities that should be done by the walk date, indexes the walk in a private Vivu project for that walk date, finds the moments where the walker names a room (or reads the sign that opens each room's clip), and looks at full resolution frames of each confirmed room to name its construction stage. In a full run it also searches the walk for three stages (bare studs, drywall hung but not finished, ceiling grid with no tiles) to point at moments worth checking. It writes progress_check.csv (planned against seen, per room and activity) and delays.md grouped by subcontractor, and with the user's approval posts one Slack message per subcontractor.

The value is in what only the footage shows. The schedule says what should be done and the subcontractor's daily report says it is done; the walk video is the one record of the room itself, and nobody says "the drywall in 103 is not hung" on camera. The stage is only visible: studs you can see through, rows of bare screw heads, T-bars with nothing in them. The room is the hard part. A stage seen on camera counts only where a sign, a transcript or the user ties that stretch to a schedule room, so a room nothing confirms stays NOT SEEN. Vivu's stage search is a pointer here, not a judge: it often returns a neighboring stage described with confidence (finished walls called bare drywall, curved bulkhead framing called ceiling grid), so every result is checked on frames, and a subcontractor only hears about a delay that a checked frame shows.

When to use

Use when someone asks to check this week's site walk against the schedule, find which rooms are behind, turn a walkthrough video into a list for subcontractors, or check framing, drywall or ceiling grid progress from walk footage. For one question about one video ("did we film the lobby ceiling?"), search Vivu directly. This skill does not do safety or quality inspections, punch lists, percent complete, or anything that identifies workers; use your inspection or punch list tool for those. Stages other than framing, drywall hang, tape and finish, ceiling grid and ceiling tile (MEP rough-in, flooring, paint colors) are not covered, because no search wording was tested for them.

Working principles

  1. Report measured numbers, not estimates. When a number is an estimate, say so.
  2. Vivu's results are candidates. Nothing reaches the report until Claude has looked at frames from inside the window and named the state it sees. The reason text and Vivu's summaries are never evidence on their own.
  3. BEHIND and ON TRACK each need two checked facts: the room (a door or paper sign read from a frame, or a spoken room name checked against a transcript or confirmed by the user playing that moment) and the stage (a full resolution frame of that room). Anything short of that is NOT SEEN, which means the footage did not show it, not that the work is late.
  4. Stop and tell the user when a required capability or tool is missing. Do not guess around it.
  5. Ask the user before anything that costs index minutes or search credits (Step 4) and before anything that acts on their behalf (Step 9, messages to subcontractors).

What you need before starting

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

Requirement Why How to check
Vivu connector with write access create a private project per walk date, open its upload page, search, read summaries 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: ask the user to reconnect Vivu with write access
A shell on the machine that holds the walk videos, with ffmpeg and ffprobe durations for pricing, frames and crops for every check, contact sheets, cutting stretches out ffmpeg -version and ffprobe -version
This week's walk videos as local files (mp4 or another common format; 360 footage exported flat) Vivu indexes the files you upload, and frames are cut from your copy ls the folder and ffprobe one file
The schedule: a CSV export (P6, MS Project, a spreadsheet), or a Todoist or Linear connector with read access the expected table in Step 2 open the CSV, or list the project's tasks once
A browser the user can open the upload page in, or a browser tool that can attach local files moving files into Vivu ask the user; for Claude in Chrome, check that it is connected
For walks where rooms are named by voice: a transcript of the walk (from the camera app or a speech to text tool the user already has), or the user's time to play each named moment checking each spoken room name against what was said; a Vivu summary alone never confirms a room ask the user; without a transcript, Step 7 asks the user to play each moment
Slack connector with access to each subcontractor's channel (only for Step 9), with a file upload tool for the frames the messages and the frames they carry read each channel once and look for a file upload tool in the connector

The skill runs in Claude Code on the user's computer (terminal or the Code tab of Claude Desktop), because it needs a shell and the walk files on local disk. It needs no residential IP, since nothing is downloaded from YouTube. It sets up no scheduled task: a walk exists only after someone films it, so run the skill once per walk.

Inputs to collect

Ask for anything missing, most important first.

  1. The walk videos and the walk date (required).
  2. The schedule source, and which fields hold room, activity, planned finish date and subcontractor (required).
  3. How rooms are marked in the footage (required): one clip per room that opens on the door sign or a paper sign with the room number, or one continuous walk where the walker says each room name when entering. Default when the user is not sure: continuous walk; Step 3 checks whether any room names are in it before anything is spent.
  4. Full run or rooms only run (Step 4 explains the difference). Default: full run for a continuous walk, rooms only for one clip per room.
  5. The activities to check. Default: every scheduled activity in the Step 2 table that is due on or before the walk date.
  6. Where subcontractors get messages. Default: nowhere; the report stays in the working folder.
  7. The working folder. Default: site-walk/WALK_DATE/ next to the videos, where WALK_DATE is the walk date written YYYY-MM-DD.
  8. The Vivu project name. Default: "Site walk PROJECT_NAME WALK_DATE", where PROJECT_NAME is the job's name: one private project per walk date, because a search covers every video in its project and older walks would crowd this week's results.

Files and state

site-walk/WALK_DATE/
  config.json          walk date, schedule source and field mapping, activity to search mapping, full or rooms only run, spoken name to room mapping, Vivu project id for this walk date, subcontractor destinations, whether Slack can attach files
  walks.csv            walk_file, duration_s, stored_name, video_id, room marking (sign clips or spoken names), cut_from (original walk and start second, for a cut part)
  expected.csv         schedule rows due on or before the walk date
  results/FIELD.json   raw result of each search, saved as returned (a local cache)
  frames/              frames and crops from every checked window
  rooms/               sign frames, contact sheets, and full resolution frames and crops from direct looks
  rooms.csv            confirmed rooms: sign or spoken name, how it was checked (transcript or the user), the time span it covers
  observations.csv     every checked window: field, window, real or false for its query, state seen, frame paths, room
  progress_check.csv   the report
  delays.md            BEHIND by subcontractor, NOT SEEN by walk
  state.json           uploaded video ids, finished searches with job ids, checked windows, confirmed room names, messages sent (keyed by walk date, room and activity)

state.json lets a rerun resume: skip uploads whose video id is recorded, searches that have a saved result, windows already in observations.csv, and room names the user already confirmed. Each walk date has its own folder and its own Vivu project, and message keys are checked before any post, so a rerun never messages the same delay twice.

Step 1: Check the Vivu connector and the setup

Goal: confirm everything in the table above.

  1. Call vivu_get_account. If the tool does not exist, 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 later write fails with "has not granted vivu.write", ask the user to reconnect Vivu with write access and stop.
  2. Run ffmpeg -version and ffprobe -version. If either is missing, ask the user to install ffmpeg.
  3. Open the schedule once. If Slack messages are wanted, read each subcontractor channel once and check whether the Slack connector has a tool that uploads a file. Without one, Step 9 writes "Frame available on request." instead of attaching the frame; tell the user now, since a delay claim without its frame is weaker.

Done when vivu_get_account shows can_create_projects: true, both ffmpeg commands print a version, the schedule opens, and config.json records whether Slack can attach files.

Step 2: Build the expected table from the schedule

Goal: expected.csv, the rows the walk should confirm.

  1. Read the schedule. From a CSV, use the columns the user named. From Todoist or Linear, list the project's tasks and read room and activity from the task title or labels; ask the user how they are written. The skill only reads the schedule and never edits it.
  2. Keep rows whose planned finish date is on or before the walk date and whose activity maps to a stage Claude can judge from frames:
Schedule activity Search that points to it (Step 6) Done when a checked frame shows Behind when a checked frame shows
Metal stud framing open_framing studs standing where the walls go an open floor with no studs
Drywall hang open_framing, drywall_hung boards on the walls studs only
Tape and finish drywall_hung taped joints, smooth or painted walls boards hung with bare screws and joints
ACT grid ceiling_grid grid overhead, with or without tiles open deck, no grid
Ceiling tile ceiling_grid tiles in the grid grid with no tiles
  1. List the activities left out (MEP rough-in, flooring, paint and the like) so the user knows the report does not cover them.
  2. Show the user the mapping, the count of expected rows and one sample row, and wait for a yes.

In our test run the schedule was an example CSV written for the public test footage, since the real schedule was not available, with placeholder subcontractors. Reading Todoist or Linear, and the user's confirmation, were not exercised in our test run.

Done when expected.csv exists and the user has approved the activity mapping.

Step 3: Collect the walk videos and check the rooms

Goal: walks.csv with every file, its length and how its rooms are marked, and the user knowing which schedule rooms the footage can confirm before anything is spent.

  1. Ask how the walk was filmed. One clip per room should give the report the most rows it can judge, because the room then comes from a sign in the first seconds; this is reasoning, not a measurement. A continuous walk only yields rooms where the walker said the name on camera, and everything between named rooms stays NOT SEEN. For the next walk, suggest one clip per room that opens with 2 seconds on the door sign or a paper sign with the room number, then pans the walls and the ceiling slowly.
  2. 360 cameras: export flat video (equirectangular or reframed) from the camera app. The ceiling then sits along the top of each frame; Step 6 crops it for ceiling checks.
  3. Measure each file:
ffprobe -v error -show_entries format=duration -of csv=p=0 WALK_FILE

WALK_FILE is one video from the walk folder.

  1. Check that rooms can be tied before any spend. With a transcript, count each schedule room name (or the word the walker would say for it) in each walk's transcript:
grep -i -c "ROOM_NAME" TRANSCRIPT_FILE

ROOM_NAME is one room name or its spoken form ("closet", "phase two") and TRANSCRIPT_FILE is the transcript of one walk. A count of 0 for every word the walker might use means that room's rows will come out NOT SEEN for this walk, unless a sign shows the room. Without a transcript, ask the user whether the walker named rooms out loud or filmed signs, and which ones. If no room in expected.csv can be tied, tell the user the report would be all NOT SEEN, recommend re-filming (one clip per room that opens on a sign), and let them decide before anything is indexed or searched.

  1. To leave stretches out (people who should not be uploaded, or footage outside the rooms in expected.csv, to save index minutes), keep only the stretches you need with a stream copy, which does not re-encode:
ffmpeg -v error -ss START -to END -i WALK_FILE -c copy WALK_NAME_partN.mp4

START and END are seconds in the original walk, WALK_NAME is the walk file's name without its extension, and N numbers the parts. A stream copy starts at the nearest keyframe at or before START, so measure each part with ffprobe and record it in walks.csv with cut_from (the original walk and START). Every MM:SS in the report and the messages then refers to the part file, not the original walk.

Per room clips and sign reading were not exercised in our test run: the walks were continuous and showed no room signs. The room check on local captions found a schedule room name only for the rooms that Step 7 later tied to footage, and every row whose room name never appears in its walk's captions came out NOT SEEN. The cut command was checked on a copy of one test walk; uploading cut parts was not exercised in our test run.

Done when walks.csv lists every file with duration_s and its room marking, and the user has seen which schedule rooms the footage can confirm (or chose to go ahead knowing most rows will be NOT SEEN).

Step 4: Choose the run, size it and get approval

Goal: the user picks a full or rooms only run and approves the cost before anything is uploaded.

  1. Index minutes = the sum of duration_s of the files to upload, divided by 60.
  2. Searches are counted per run, because a search covers every video in its project and each walk date gets its own project (Step 5). A continuous walk needs one room search; sign clips need none. A full run adds one stage search for each search in the Step 2 table that points to an activity with due rows, at most three. All are precise. A precise search uses 5 credits in total, and each reworded or repeated search costs another 5, so a continuous walk takes about 20 credits in a full run and about 5 in a rooms only run by this estimate. Whether a maximum_results above 10 costs more credits is untested; the estimate assumes it does not. A fast search costs 1 credit, but this skill does not use fast mode (Step 6 says why).
  3. Explain the choice between the two runs. By this skill's rules a stage window only counts inside a confirmed room, and Step 7 looks directly at every confirmed room that has no window. So the stage searches save frame looking inside named rooms and list the times where a stage shows outside them (the re-walk list); they never add a room. In our test run they added no judged row that a direct look at the named rooms missed. With a sign clip for every room and a rooms only run, nothing needs Vivu at all: say so, skip Steps 5 and 6, index nothing, and go on to Step 7.
  4. Call vivu_get_usage for the plan and what remains this month. For reference, Free is 20 indexing minutes a month and 50 search credits a month; Premium is $30 a month for 180 indexing minutes a month and 500 search credits a month.
  5. Show one table:
This walk Remaining this month Fits
Index minutes sum of durations from vivu_get_usage yes or no
Search credits (estimate) searches × 5 from vivu_get_usage yes or no
  1. If it does not fit, offer these levers in order, each with its saving: a rooms only run (about 15 credits less per walk, by this estimate); index only the clips or stretches for rooms with rows in expected.csv (Step 3, item 5); skip stage searches that point to no due rows; move from Free to Premium last. For example, four 15 minute walks a month is 60 index minutes, more than the Free plan covers, and four full runs at an estimated 20 credits each come to an estimated 80 credits, more than the Free plan's 50 search credits a month.

The approval exchange and the choice between runs were not exercised in our test run: it ran every search on an admin account that reports no remaining allowance.

Done when the user has chosen a full or rooms only run, seen the table and said yes.

Step 5: Create a private project for this walk date and upload

Goal: every walk file shows ready in Vivu. A rooms only run on sign clips needs no search, so it skips this step.

  1. Confirm the Compliance points with the user.
  2. Call vivu_list_projects. Reuse a project only when its name is this job and this walk date (a rerun of the same walk). Otherwise call vivu_create_project with the project name from Inputs and visibility "private". One project per walk date keeps each search to this week's walk: a search covers the whole project, and older walks would take candidate slots with windows whose files are not in this folder. The default visibility is the whole organization, which is wrong for a client's site with drawings, door codes or patient areas on camera.
  3. Call vivu_open_upload_page with the project ID right before the upload. The upload_url is a one time sign in link that expires in 180 seconds, so request it only when the user or the browser tool is ready, never paste it into a message, and request a new one if it lapses.
  4. Give the link to the user to open in their own browser and select the files, or open it with a browser tool that can attach local files. Claude in Chrome takes at most 10 MB per upload call, and walk videos are usually larger, so most users select the files themselves. If a file will not go through, ask the user to add it in the Vivu web app. Never split or recompress a walk to fit the upload tool's size limit.
  5. Poll vivu_list_videos until every video shows ready. Vivu replaces spaces and brackets in file names with underscores; match rows in walks.csv by the name with those characters replaced and by duration_ms. Record stored_name and video_id.

In our test run the upload page was opened by an automated browser on our machine, not by a user, and the three walks were ready 704 seconds after the link was requested. The three walks shared one project in our test run; one project per walk date was not exercised in our test run.

Done when vivu_list_videos shows every walk file as ready and each is matched to a row in walks.csv, or the run needs no search and nothing was uploaded.

Step 6: Search the stages and check every candidate on frames (full run only)

Goal: observations.csv, one row per returned window, each with the state Claude saw. In a rooms only run, skip this step; Step 7 looks at every confirmed room directly.

The chain: a stage search narrows a long walk to the few windows where a stage might show; frames from each window let Claude decide what is really there; Step 7 then decides which room those frames show. The stages come only from the picture, the room names in continuous walks come from speech, and a row needs both. A window outside every confirmed room changes no row; its state and times go on the re-walk list in delays.md.

Field Query Mode
open_framing (studs only) new wall framing in progress: rows of bare metal studs standing between a track on the floor and a track overhead, with nothing attached to them yet precise
drywall_hung (hung, not finished) raw paper-faced drywall on the walls with dotted lines of dark screw heads, no white joint compound stripes over the seams and no paint yet precise
ceiling_grid (grid, no tiles) thin white metal T-bars hanging on wires below the exposed roof deck, making an empty checkerboard of open squares overhead where ceiling tiles will go precise

Each wording is the one kept after 2 rewordings on the same corpus, so expect different results on other sites. Run only the searches that point to an activity with due rows (Step 2 table).

  1. For each stage, call vivu_search_videos with project_id, query, mode "precise" and maximum_results set to the number of rooms in expected.csv whose activity this search points to, at least 10 and at most 100. The value is the recall ceiling: a smaller number silently drops windows. fast mode is not used: it returns whole files with no reason text, and every check needs a time range to cut frames from.
  2. Call vivu_get_search_results with the job ID until complete is true. Each call can wait up to 45 seconds, so a pending search is not a stalled one. Save the returned JSON unchanged as results/FIELD.json, a local cache that lets a rerun skip finished searches, and record the job ID in state.json. The cache keeps the Vivu result page link as returned; that link can go in the live reply, and since it expires after four hours it never goes into progress_check.csv, delays.md or a message.
  3. Drop any window whose video_id is not in walks.csv (an older walk in a reused project) before checking, and tell the user how many were dropped.
  4. For every remaining window, extract frames at the start, the middle and the end, plus one frame every 5 seconds in between when the window is longer than 20 seconds:
ffmpeg -v error -ss SECONDS -i WALK_FILE -frames:v 1 -q:v 3 site-walk/WALK_DATE/frames/FIELD_RANK_SECONDS.png

SECONDS is the frame time (start_ms divided by 1000, and so on), FIELD the query field, RANK the result's position in the saved result.

  1. Whenever you name a ceiling state (open deck no grid, grid no tiles, tiles in) from 360 footage, whichever search returned the window, also crop the top third of the full resolution frame and enlarge it, because thin white T-bars disappear at normal size:
ffmpeg -v error -ss SECONDS -i WALK_FILE -frames:v 1 -vf "crop=iw:ih/3:0:0,scale=iw*2:-1" -q:v 3 site-walk/WALK_DATE/frames/FIELD_RANK_SECONDS_top.png
  1. For a wall finish (bare screws and joints, taped, finished), enlarge the half of the frame that shows the wall:
ffmpeg -v error -ss SECONDS -i WALK_FILE -frames:v 1 -vf "crop=iw/2:ih/2:X:ih/4,scale=iw*2:-1" -q:v 3 site-walk/WALK_DATE/frames/FIELD_RANK_SECONDS_zoom.png

X is 0 for the left half of the frame or iw/2 for the right half. Pick the half with the wall and, where you can, no people; Step 9 attaches these crops.

  1. Look at every frame and name the state it shows, using only these words: studs only, boards hung not finished, walls finished, open deck no grid, grid no tiles, tiles in, can't tell. When plywood, stored boards or equipment cover most of a wall, that wall is can't tell. Judge from the frames. The reason text describes neighboring stages with confidence and is never evidence.
  2. Write one row per window to observations.csv: field, window (MM:SS from start_ms and end_ms), real or false for its query, the state seen, frame paths. A window whose frames show a different stage is a false positive for its query: count it and tell the user. Its state still goes in the row, since a checked frame of finished walls is evidence about that spot. A window that only shows can't tell records no state and can never lead to BEHIND.
  3. Tell the user the counts per stage: returned, real, false.
Worked example from our test run

In our test run on 3 public site walk videos (18.09 minutes of weekly progress walks by a commercial interiors contractor, filmed with a handheld spherical camera and exported flat; two walks of one clinic a few weeks apart and one walk of another clinic's framing phase), we marked the stages by hand on contact sheets before any search. Each stage search ran with maximum_results 10, and its wording came after 2 rewordings on the same corpus. Two independent blind reviewers then judged every returned window again, with arbitration on disagreement; that moved one ceiling window from false to real.

  • open_framing returned 8 windows: 2 real and 6 false, and it missed 1 stretch of the framing we had marked. The false ones were drywalled walls, a bare metal door frame and a narrow framed chase.
  • drywall_hung returned 10: 6 real, 4 false, 1 missed. All three walks shared one project, so every search covered all of them, and all 4 false windows were in the other two walks: finished, painted walls and a dark framing area. One project per walk date keeps other walks out.
  • ceiling_grid returned 6: 3 real, 3 false, 1 missed. The false ones were open deck. One real window, a corridor from 02:19 to 02:32, only showed its grid once the top of the frame was cropped and enlarged; at normal size we had judged it open deck. We then ran the same crop on every other window of this search: it showed the grid in the real windows and no T-bars in the open deck ones. Windows from the wall searches that showed grid overhead in passing were not cropped, and none of them sets a report row.

The walks were ready 704 seconds after the upload link was requested. Median windows were 12, 14.5 and 10 seconds wide. The run used 10 precise searches, an estimated 50 credits. All of this is spherical footage of two clinics; ordinary phone footage and other building types were not tested.

Done when every returned window from this walk has a row in observations.csv with a state (or can't tell) and its frame paths and the user has seen the counts per stage, or the user chose a rooms only run.

Step 7: Tie what was seen to rooms

Goal: rooms.csv, a room or UNCERTAIN on every row of observations.csv, and a direct look at every confirmed room that has due rows and no observation.

Rooms come only from two sources: a door or paper sign that Claude reads from a frame, or a room name the walker said, checked against a transcript or confirmed by the user. Room numbers in Vivu's reason text or summaries never decide a room.

  1. One clip per room: extract the frame at 1 second and read the sign. A file name with the room number is a hint that the sign frame confirms. With no readable sign, the clip's room is UNCERTAIN.
  2. Continuous walk: search for spoken room names with this query. Use maximum_results equal to the number of rooms in expected.csv, at least 10.
Field Query Mode
room_named the person filming says out loud which room or area they are walking into or standing in precise
  1. Check every returned window against what was said. With a transcript, read the stretch around the window and accept the name only when the words are there. Without one, list each window for the user as WALK_FILE at MM:SS (from start_ms) and ask them to play it and say which room is named; until they do, that room stays UNCERTAIN. vivu_get_video_summary with include_segments true and start_ms and end_ms around the window is a second signal only: use it to decide which windows to ask about first, never to confirm a name, because it is Vivu's paraphrase like the reason text, which can invent a room number.
  2. For each confirmed name, extract a frame at the moment it is said and compare it with the frames of each observation you want to tie to it. Tie them only when both show the same space and the frames show the named room itself: walkers often name a room while looking into it from the next one. The span ends at the next confirmed name or where the frames stop showing that room.
  3. Map spoken names to schedule rooms ("phase two" to Phase 2 open area, for example) and have the user confirm the mapping.
  4. Direct look: for each row in expected.csv whose room has a confirmed span but no observation (every such row in a rooms only run), make contact sheets of the span to find the moment to check:
ffmpeg -v error -y -ss START -t LENGTH -i WALK_FILE -vf "fps=0.5,scale=480:-1,tile=3x6" -frames:v 1 site-walk/WALK_DATE/rooms/ROOM_START_sheet.png

START and LENGTH are in seconds and ROOM is the schedule room without spaces. The sheet holds one frame every 2 seconds for up to 36 seconds; make one sheet per 36 seconds of a longer span. The sheet only finds the moment to look at. Before naming any state that sets a row BEHIND or ON TRACK, extract a full resolution frame at that moment:

ffmpeg -v error -ss SECONDS -i WALK_FILE -frames:v 1 -q:v 3 site-walk/WALK_DATE/rooms/ROOM_SECONDS.png

Add the crops from Step 6 with the output named rooms/ROOM_SECONDS_top.png or rooms/ROOM_SECONDS_zoom.png: the top band for a ceiling activity in 360 footage, the enlarged wall half for a wall finish. Name open deck no grid only when the enlarged top band shows no T-bars and no wall angle. When plywood, stored boards or equipment cover most of the walls, the wall is can't tell. A state seen only on a sheet is can't tell.

Sign reading, per room clips, and the path where the user confirms spoken names by playing them were not exercised in our test run.

In our test run the room search returned 10 windows: 6 real, 4 false, 0 missed, checked against local captions. vivu_get_video_summary returned no segments for one walk; on the other two its segment titles matched the confirmed names, which is why it stays a second signal. In one walk the walker named the IT closet while standing in the room next to it, so the ceiling grid in that window belonged to the other room. A direct look at the closet's span found plywood blocking over most of its walls in the full resolution frame, so its tape and finish row is NOT SEEN.

The confirmed rooms decided what the stage searches could add. Of the 24 windows they returned, 11 were real; only the 2 real framing windows and the first real drywall window fell in a confirmed schedule room (a false ceiling window did too, in a room with no ceiling row). The rest stayed UNCERTAIN, fell in named areas the schedule does not list, or showed the room next to a named one. We also ran the direct look on the two spans behind the BEHIND rows without using any stage window, and it named the same states from full resolution frames. So in this run the stage searches added no judged row; they added the times listed under NOT SEEN.

Done when rooms.csv lists every confirmed room with its source and span, the user has confirmed the name mapping (and every spoken name when there is no transcript), every row of observations.csv has a room or UNCERTAIN, and every confirmed room with due rows has an observation or a direct look.

Step 8: Build progress_check.csv and delays.md

Goal: the report, one row per row of expected.csv.

  1. For each row in expected.csv, collect the rows of observations.csv (and direct looks) from that walk whose room matches. Then set the status:
    • BEHIND: the room is confirmed and a full resolution frame of it (or an enlarged crop) shows the stage before the activity (the Behind column in Step 2).
    • ON TRACK: the room is confirmed and a full resolution frame of it (or an enlarged crop) shows the activity done. A contact sheet alone never sets BEHIND or ON TRACK: a false ON TRACK hides a delay from the user as surely as a false BEHIND blames the wrong trade.
    • NOT SEEN: everything else. No frame of that room, frames that only show can't tell, an UNCERTAIN room, or frames that disagree. NOT SEEN is never turned into BEHIND.
  2. Show the user one sample row and the field mapping before writing the rest.
walk_date,walk_file,room,activity,subcontractor,planned_done_by,source_task,observed_state,evidence_mmss,frame,room_check,status,note
2026-09-22,103.mp4,103,Drywall hang,DRYWALL_SUB,2026-09-18,103 Drywall hang,studs only,00:14,frames/open_framing_1_14.png,door sign at 00:01,BEHIND,no boards on the new walls in the checked frame
Field Source If unavailable
room, activity, planned_done_by, subcontractor, source_task the schedule (Step 2) row left out
observed_state the state Claude named from full resolution frames (Step 6 or a direct look) blank, status NOT SEEN
evidence_mmss, frame the checked frame's time and file (a full resolution frame or crop, never a sheet) blank
room_check the sign frame, or the spoken name and how it was checked (Step 7) UNCERTAIN, status NOT SEEN
status the rules above NOT SEEN
  1. Write progress_check.csv, and delays.md with BEHIND rows grouped by subcontractor and NOT SEEN rows grouped by walk, as the list of rooms to film properly next time, with the times where a stage window showed something outside any confirmed room. Link evidence by file name and MM:SS only; Vivu result links expire and the report outlives them.
  2. Tell the user the count per status and show delays.md. Report the real counts even when most rows are NOT SEEN; never fill a row from the reason text or from a neighboring room.

In our test run, with the example schedule, both BEHIND rows came from rooms the walker named on camera and a full resolution frame of the same space, and every stage window outside a confirmed room stayed NOT SEEN. The IT closet row had been ON TRACK from a contact sheet in an earlier pass; with a full resolution frame it became NOT SEEN, because plywood covers most of the walls. The sample row confirmation was not exercised in our test run.

Done when progress_check.csv has one row per row of expected.csv, every BEHIND and ON TRACK row has a confirmed room and a full resolution frame or crop file that exists, and the user has seen delays.md.

Step 9: Message subcontractors after approval (optional)

Goal: each subcontractor with a BEHIND row gets one message, only after the user approves it.

Posting to Slack acts as the user, and telling a subcontractor they are late when they are not costs trust on site.

  1. Name the destination for each subcontractor, show one fully rendered message, and list every frame file that would be attached to any message, since the user sees only one sample. Wait for an explicit yes before the first post, and ask again if a destination changes.
  2. Send one message per subcontractor per walk, BEHIND rows only. Attach the enlarged crop from Step 6 or Step 7 that shows the walls; if people are in it, use the other half of the frame or another moment. If Step 1 found no file upload tool, write "Frame available on request." instead of attaching:
Site walk WALK_DATE, PROJECT, TRADE: N rooms behind the schedule.
- ROOM: OBSERVED_STATE at MM:SS of WALK_FILE (ACTIVITY was due PLANNED_DATE). FRAME_NOTE
Reply here if the schedule changed or if I have the wrong room.

PROJECT and TRADE come from config.json and the schedule, N is the number of BEHIND rows in the message, FRAME_NOTE is "Frame attached: FRAME_FILE" or "Frame available on request.", and the other placeholders come from that row of progress_check.csv. NOT SEEN rows never go to subcontractors; they are the user's list for the next walk. 3. Before each post, look up the message key (walk date, room, activity) in state.json, and record it after posting.

In our test run the messages were rendered to files and not sent; the file upload check, the approval exchange and the Slack post were not exercised in our test run.

Done when every approved message is posted and recorded in state.json, or the user has declined and the report stays in the working folder.

Compliance

  1. Rights to the footage: the walk is normally the user's own footage of a site they work on. Footage from someone else (an owner's rep, another contractor) needs their permission and stays internal. Owners, hospitals and government sites often restrict filming, so have the user check the site's rules before Step 5.
  2. People on camera: walks catch workers. The skill describes rooms and stages only, never names or identifies anyone, and messages talk about the work, not people; the frames sent to subcontractors are crops of the walls (Step 9). Confirm before Step 5 that the site allows the recording.
  3. Minors and the public: occupied sites (open clinics, schools) can put patients, visitors or children on camera. Leave those stretches out of the upload with the Step 3 cut command, or get explicit guardian consent for children, before Step 5.
  4. Where the videos go: uploaded walks stay in the user's Vivu project for that walk date until the user deletes them. The skill creates each project as private and never deletes projects or videos unless the user asks, and then confirms first.
  5. Acting on the user's behalf: messages to subcontractors go out only after the approval in Step 9.
  6. What the skill does not do: no face or identity recognition, no safety or code compliance judgment, no percent complete.

Known failure modes

Symptom Cause Fix
(observed) finished, painted walls come back as unfinished drywall, with reason text such as "dotted lines of dark screw heads"; the drywall search returned 10 windows: 6 real, 4 false, and 1 stretch we had marked was missed the search describes a neighboring stage with confidence judge every window from frames, never from the reason
(observed) curved bulkhead framing and open deck come back as ceiling grid; the ceiling search returned 6 windows: 3 real, 3 false, and 1 marked stretch was missed curved metal and bare deck in a wide frame read as runners look for T-bars and wall angle in the cropped top of the frame before calling it grid
(observed) drywalled walls, a bare metal door frame and a narrow framed chase come back as open studs; the framing search returned 8 windows: 2 real, 6 false, and 1 marked stretch was missed studs showing in a small spot read as a stud wall call studs only when the frame shows walls you can see through
(observed) a real ceiling grid over a corridor is judged open deck thin white T-bars at the top of a spherical frame vanish at normal size crop the top third of a full resolution frame and enlarge it (Step 6)
(observed) windows from other walks come back when walks share a project; all 4 false drywall windows were in the other two walks a search covers every video in its project one project per walk date (Step 5); drop windows whose video_id is not in walks.csv (Step 6)
(observed) a room search result quotes "I'm in room 101", which nobody said the reason text paraphrases and can invent words confirm spoken names against a transcript, or have the user play the moment (Step 7)
(observed) the walker names a room while standing in the next one the name marks where the walker is looking, not always where the camera is tie a frame to a room only when it shows the named room itself
(observed) vivu_get_video_summary returns "segments":[] for a walk no section summaries for that video use a transcript or the user's check; the summary is only a second signal
(observed) plywood blocking covers most of a room's walls in every frame of it protection or backing in front of the finish call the wall can't tell; the row stays NOT SEEN until a later walk shows the finish
(observed) "Error executing tool vivu_search_videos: 503 Stream removed (recvmsg:Connection reset by peer (104))" a transient connector error on submit submit the search once more; it returns a new job ID
most rows come out NOT SEEN a continuous walk with few rooms named on camera the Step 3 room check shows this before any spend; film each room as its own clip that opens on the door sign
a stage that is there does not come back recall is capped by maximum_results, and a search can miss stretches that are there raise maximum_results to the room count and use the direct look; an empty result does not prove the stage is absent
"has not granted vivu.write" Vivu connected read only reconnect 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 file above the tool's size limit the user adds that file in the Vivu web app
a result's file name does not match walks.csv Vivu normalized the file name match on the name with spaces and brackets replaced, and on duration

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.