Aug 10 →
Aug 28
Lightroom catalog performance and reorganization
Lightroom Classic
Years of severe launch and browse lag traced to OneDrive Files On-Demand sitting in the catalog's SQLite and preview I/O path, followed by a reorganization of which images live in which catalog.
Updates
- Aug 10 Catalogs moved out of OneDrive to local storage — roughly 1.4GB of catalog and 24.6GB of previews for the main one. Preferences repointed with backups saved first, and backup-on-exit redirected to a OneDrive folder so the safety net survives without the lag. Standing rule recorded: photo libraries stay on SharePoint, catalogs and previews never sit in a synced folder.
- Aug 28 Catalogs reorganized by subject. A staff headshots catalog was merged in, and the office image library photos were separated out of the projects catalog into a catalog of their own. End state: three separate catalogs — Project Image Library, Office Image Library, and Portraits.
CompleteThree catalogs, all local, all separate; backup-on-exit targets a OneDrive folder.
Aug 13–17
Invoice email auto-filing
Graph · shared mailboxes
BQE's invoice and past-due notifications pile up in the accounting inbox and have to be filed into the right project folder in the right project-year mailbox. This does it: the project number is parsed from the message body (not the subject, which carries invoice numbers), the year maps to the corresponding project-year shared mailbox, and a faithful copy is imported into the existing project folder with original timestamps and read state preserved, verified, and only then is the inbox original archived.
The safety contract is stated in the file header: never creates folders, never guesses, never deletes. Unresolvable messages are skipped and logged. A companion script lists which active projects are missing a folder in their year mailbox so a person can create them.
21 invoices filed in the first live run on the accounting inbox
In progressProven on the accounting inbox. Next: test against a PM inbox, then move from this laptop to an event-driven Azure Function with a managed identity.
Jul 16 →
Aug 28
Project mail folder cleanup and naming
Exchange · Outlook COM · Graph
The shared project mailboxes had accumulated pursuit mail folders that no longer correspond to anything, plus folders left behind when a pursuit converted to a won project. Each mailbox's folder tree is cached offline first — folder names and item counts only, never message content — so the analysis runs without a live session.
Two questions are answered per year on exact identifiers only: which pursuit folders have no matching server folder, and which match a real project folder in the same mailbox, meaning the pursuit converted and the folders should merge. Fuzzy matching was tested and rejected after it paired two different addresses that shared only a street name. Item counts are read from the archive as well as the primary mailbox, because these mailboxes keep folder structure in the primary while the mail itself sits archived — a primary-only count reports every folder as empty. Every script is rename-only; nothing is moved, copied or deleted.
Updates
- Jul 16 Won projects have their mail folder renamed to the final project name and moved from the Potential tree into the Projects tree.
- Aug 28 Naming convention enforced as
<project> - <client>. Seven folders for one client had it reversed, which broke every downstream name parser — everything after the dash reads as the client, so all seven collapsed to the client's name. Corrected.
- Aug 28 Rename script rewritten for reliability after a recursive archive walk hung twice at thousands of COM round trips; the direct version steps down known paths in about 25 calls.
- Aug 31 Merges executed for 2012–2017, against the archive store by direct navigation to known paths rather than a recursive walk. Items are snapshotted before moving, because the collection is live and moving while enumerating skips every second message. Two cases were held back rather than guessed: one pursuit excluded because it was not confirmed to be the same project, and one where the worklist proposed two mutually exclusive destinations.
- Aug 31 Round two run on the rulings for the held cases, including one project that had no mail folder at all — created to match the repository name so the mail landed on the right job rather than on the different project at the same street address.
- Aug 31 Merged-out folders deleted from both the archive and primary trees, since the two are independent and deleting one leaves the other drifting. Each folder is re-checked for zero items immediately before deletion in the store being deleted from; any folder still holding mail, or holding subfolders, is refused. Deletions land in Deleted Items and stay recoverable.
- Aug 31 Live audit of every potential mail folder still holding mail, across all years, to cross-check against pursuits marked Won — a Won pursuit that still has its own mail folder is unfinished cleanup.
In progress2012–2017 merged and the emptied folders removed. Remaining years working through the audit.
Aug 17–18
InDesign batch relink after the library migration
SharePoint · InDesign ExtendScript
The marketing library was renamed and renumbered (the project image folder was renamed and renumbered inside a new document library), which broke the stored absolute image path in every InDesign document at once — the firm book, brochures, EOY presentations, per-project sheets going back to 2010. A read-only script snapshotted the sync migration before and after and answered whether the leftover folder was safe to delete; it never deleted anything itself.
The relink script derives each new path by rewrite rule from the stale one, confirms a file exists there, and relinks only on confirmation. Filename search is deliberately not used: the library stores multiple resolutions under identical filenames, so name matching could substitute a low-res copy — a wrong image that looks fine is worse than a visibly broken link. A verification re-run one minute later reported zero newly relinked, which is the pass condition.
1,628 links audited · 103 documents opened · 967 links relinked across 88 documents and 294 images · 9.1 minutes · 640 no-rule and 21 not-on-disk remaining, categorized
Complete661 links left broken by decision — they point at the retired Y: server, whose content was reorganized rather than moved (32 resolvable of 593 measured).
Aug 18
License table: Excel to InDesign registration page
Excel · Python · InDesign
The principal's PE/RA licenses live in Excel but also have to appear in the InDesign qualification documents, so every new license meant updating several places by hand. The pipeline is two stages because ExtendScript cannot read .xlsx: Python flattens the workbook to CSV, then an InDesign script replaces only the text inside the two license lists — creating, moving, resizing, restyling and deleting nothing.
Real domain judgment is encoded as rules: leading zeros are kept because they are part of the number as issued and stripping them can break a state board's lookup; State 1, State 2 and State 3 say "Structural Engineer" in the sheet but issue no separate SE license, so they stay in the PE list. Dry-run and work-on-copy both default on, and the review copy is written outside the synced Templates folder so it never syncs to the whole team.
In useExcel is the single source; the same CSV can feed other destinations via Power Automate.
Aug 17–26
Billing task flows
Planner · Power Automate · Outlook
A closed loop for the monthly billing cycle in Planner. One flow runs every Wednesday at 7am but fires only in the week before the first Wednesday of the month, creating one billing task per PM with the details filled in, so the cycle starts itself rather than depending on someone remembering. A second flow triggers on task completion, filters to billing tasks, and emails the operator — so she learns a PM is done without chasing anyone.
Updates
- Aug 26 Start-time condition corrected.
In use
Jul 21 →
Aug 19
Pursuit pipeline dashboards
SharePoint · Power Automate
Each project year has a six-row dashboard on its site home page — one row per pursuit status, with a count and a contract-fee sum — refreshed every morning by a flow that aggregates the year's pursuit list. Clicking a status drills through to that status filtered in the full list.
Updates
- Aug 18 Won status added to both 2026 and 2027, which had been missing from the dashboard entirely.
- Aug 19 Drill-down links pointed at the All Items view rather than the filtered Potential view, so Won drills through correctly. Won project names now link to the project's actual document folder.
- Sep 10 The daily refresh flow was still summing the old field name after the Base Fee rename. Patching it through the API was rejected, because the connector caches its schema by the field it was built against. A manual refresh script computes the six status totals directly against Base Fee as an immediate substitute; the flow itself needs the field re-selected in the designer.
In progressThe scheduled 2026 refresh flow is still running unmodified since Aug 25. Until Base Fee is re-selected in its designer, its totals are not reliable; the manual refresh script is the correct figure.
Aug 10–25
Proposal sweep
SharePoint · Graph · docx parsing
A daily 6:00am job that keeps the live pursuit list honest with no human touch: it detects the newest firm-template proposal in a pursuit folder, advances the status from In Discussion to Proposal Sent, extracts the contract fee from the proposal document, and files superseded drafts into a superseded-contracts subfolder. Ambiguous cases are flagged rather than guessed at.
Updates
- Sep 10 Defect: after the fee column was renamed Base Fee on Aug 31, the sweep kept writing every fee it computed to the deprecated Contract Fee field. Fixed to write Base Fee, and every value written in between copied across. In the pipeline kit the fee field name is now configurable rather than hardcoded, so a rename cannot silently strand it again.
First live run: 12 statuses corrected, 13 fees written, 19 superseded drafts filed
In useRuns daily, before the pipeline refresh.
Aug 19–28
Project pipeline kit
Power Automate · SharePoint · PnP
The tenant-agnostic parts of the firm's pipeline automation extracted into a separate private repo that can be deployed into any Microsoft 365 tenant. It ships three flows — pursuit folder setup, daily pipeline refresh, and full project setup on Won (Teams channel, standard folder structure, Planner plan with standard labels and buckets, proposal files moved into Contracts) — plus a surface-configuration script for list columns, views and formatters.
The README is a deployment runbook rather than a code dump: no stored secrets anywhere, a stated modularity contract with each module's "what it needs to be worth enabling," a client questionnaire as step zero, a licensing cost table, a ten-check verification list, and failure modes documented from experience — including that writing to the trigger row mid-run re-fires the trigger and stamps a successful setup as Failure, and that a naive historical backfill sets Status = Won and thereby creates duplicate channels, folders and plans for every past project.
Updates
- Aug 25 Auto-numbering, runtime name resolution and the re-trigger rule carried across from the firm's versions.
- Aug 26 Views sort and lead with the pursuit number rather than Title, so the newest pursuit lands on top.
- Aug 28 Unique pursuit number enforcement added.
In useKept in sync as fixes land in the firm's versions: patch the firm's version, port config-driven, document the reason, push both.
Aug 21 →
ongoing
Historical pursuits database, 2009–2023
file server · docx parsing · SharePoint
A searchable record of every pursuit the firm has chased back to 2009, including what each lost pursuit was worth — information that previously existed only as folders on a file server. The server is reachable only over a full-tunnel VPN that cuts the automation's own connectivity, so folder trees were cached to disk year by year (names, dates and sizes only) and every analysis run offline afterward.
Fee extraction handles three proposal conventions by era — a prose sentence for 2011–21, per-phase itemization with no total in 2022, a fee table from 2023 — and anchors on the word "fee" rather than loose currency, because these documents also contain hourly rate cards, retainers, insurance limits and construction budgets that would all look plausible as a total. Implausible values are flagged for human review rather than entering a total, and 2009–10 files in the older binary Word format are read through Word COM, recovering folders that had wrongly reported no proposal.
Pursuit-to-project matching is where the discipline shows. A first similarity-scoring pass produced 441 matches with 262 collisions — one project claimed by up to eight pursuits, because words like "West" and "Street" are shared — and was thrown out entirely. The replacement links only on evidence: a shared street number, identical distinctive names inside the right year window, or corroborating file-inventory overlap between the two folders, tiered by strength, one-to-one enforced, contested projects dropped rather than arbitrated.
Updates
- Aug 21 2024 and 2025 pursuit lists created and backfilled, mirroring the 2026 structure column for column — 507 pursuits.
- Aug 27 Raw fee tables cached per year so parsing questions can be re-answered offline; three parser bugs had each cost a full VPN round trip before this existed.
- Aug 28 List published by cloning the 2026 schema so internal names match and anything reading a year list reads this one. Scope fixed at 2009–2023, since 2024–26 have their own lists and duplicating them would create two sources of truth.
- Aug 28 Parser shorthand in the notes column rewritten into plain sentences for readers, touching only machine phrases and leaving hand-written notes alone.
- Aug 31 Completeness measured properly: a column-by-column fill rate read from the live list itself rather than from notes about it, so the gaps are counted rather than assumed.
- Aug 31 2023 zero-fee gap worked from files. Where BQE shows no contract amount, the project's master file folder is checked for a proposal or invoices, so the figure comes from a document rather than being left blank.
- Aug 31 Runbook written for the historical won-data work, and a data typo corrected.
- Aug 31 Won fees now extracted too, 2009–2022. The fee parser had only ever been pointed at pursuits that were lost; it now reads won projects' proposals as well, so the record carries what the firm charged as well as what it bid and lost. Rows written per year, then merged.
- Aug 31 Under-summed fee audit. Every row holding a single clean fee is re-checked against its source document: if the document names more than one phase, each near its own dollar figure, the extracted number may be one phase's subtotal rather than the true total. Those rows are flagged for a person to read — never auto-corrected.
- Aug 31 Year values corrected several ways — against the proposal date, sequentially, and against the live list — plus a pagination bug that had been truncating reads, an On Hold versus re-pursued distinction, and a full notes reconcile.
- Aug 31 ASCII sanitization applied to every write. Standing rule recorded: never write curly quotes, dashes or accented characters into SharePoint from any source. A source document having a curly apostrophe is not a reason to carry it downstream.
18 years cached · blank means "no fixed fee known" — writing 0 would assert the work was free · composed rows reviewed as CSV before any SharePoint write
In progressList built and populated. Ongoing: spot-check review against source, fee values flagged for review, and pursuit-to-project links where evidence was insufficient to match.
Aug 25–28
Pursuit list standardization and numbering
SharePoint · Power Automate · Graph
Pursuit lists across 2024–2027 forced to one canonical 12-column layout — same display names, same grid order, same form order. This also fixed a long-standing complaint that renames never stuck: SharePoint's UI and PnP renames silently no-op, and only a Graph PATCH on the column persists.
Pursuit numbers are now issued by the system rather than typed, rolling over at month boundaries, with flow concurrency pinned to 1 so two simultaneous entries cannot collect the same number. Uniqueness is enforced at the SharePoint level after a defect where a number was freed at project setup and handed to the next pursuit, making it unusable as a join key. A Notes column was added for relationships the schema cannot express — a job bid through two architects, a number reassigned when one pursuit became two projects — with the convention that each note names the related pursuit number so a text search finds both sides.
Updates
- Aug 26 Vocabulary standardized across all years: "Potential Projects List" became "Project Pursuits," "Potential Project Pipeline" became "Pursuit Pipeline."
- Aug 28 "Potential No" made the first column on every pursuit view in every year, including the Won view — previously the one place the pursuit-to-project link matters most was the one place it did not appear.
- Sep 2 Project Number repaired on three projects, which were written in the combined number-and-name form the day before the columns were split and kept it. The Won flow preserves whatever is already in the field, so it will not reintroduce this.
- Sep 10 The deprecated Contract Fee and Project Type fields hidden from every form. Removing a field from a view only affects the table; the item panel shows every field unless the field itself is marked hidden. Data untouched.
- Sep 10 Loss Reason added to 2026 pursuits as a multi-select, so a row can carry more than one reason: Budget, Lost to Competitor, Timing, Scope Change, No Decision, Client Delayed, Other. Each renders as a colored pill.
- Sep 10 Placing that column wrote the view's raw XML and collapsed the default view to a bare list. Restored through the view's typed properties. Rule since: never set a view's XML wholesale — SharePoint honors only some of it.
In use
Aug 24 →
Sep 1
2026 staff rate rollout
BQE API · Task Scheduler
A firm-wide bill and cost rate increase for all employees, effective 1 September, driven off a config file transcribed from the Grade Billing/Cost Rate Summary. Because everyone is salaried it also zeroes overtime rates and turns off auto-overtime. The script defaults to a dry run printing every before-and-after change; the dry run was executed and logged, and a scheduled task will apply it at 00:01 on the effective date. It runs on the public API, so it needs no browser session.
Updates
- Sep 1 Executed on schedule at 00:01. Log records the before and after rate for every person, and overtime zeroed where it had been set. Applied to all employees with none skipped.
All employees applied 2026-09-01 · 0 skipped · bill and cost rates plus overtime settings, each change logged
Complete
Aug 26
Budget rate repair
BQE API
Budget lines on a new project showed zero and could not be edited without deleting and recreating them. The cause: BQE's web UI auto-fills a budget line's bill and cost rate from the assigned person, but the public API does not, so every line the automation had ever written stored null rates. Fixed forward in the project setup script and backward across existing projects, with a clean re-scan afterward. Because rates are now read live from employee records, the September rate change flows through without touching any script. The repair also handles BQE's 100-request-per-minute cap by backing off and retrying rather than dying mid-run.
51 budget lines repaired across existing projects
Complete
Aug 26–27
Marketing activity code cleanup
BQE webapp endpoints
Standardized time-entry activity codes on the firm's internal marketing project so every marketing phase and sub-phase offers the same list. The Marketing group was applied across all 41 nodes and a stray "Billable Activity Group" removed, since the project is non-billable. Separately, deleting the obsolete "Technical Images" group had been failing with a SQL error because it was still attached to 38 phases hidden in the inactive bucket of Project Assignments; a script strips all 38 assignments so the group can finally be deleted, leaving phase names untouched. Both scripts are dry-run by default and idempotent, re-reading live state each run, and backups of prior code assignments were captured first.
41 nodes standardized · 38 stale assignments removed · backups taken before both changes
Complete
Aug 26
Client contact email maintenance
BQE webapp endpoints
BQE's public API has no contact-update endpoint, so the webapp's own update call was captured and turned into a script that edits an existing contact's email list in place — reusing the known-good create payload with the record ID and a Modified state swapped in — instead of creating duplicate contacts. Standing default recorded alongside it: every project for one architect gets a per-project contact whose email list always includes two standing billing addresses plus whatever Invoice C/O the contract names.
In use
Aug 20–27
Ops and Marketing OneNote notebooks
OneNote · Graph
Two governed notebooks built and maintained through the Graph API rather than typed: 2026 Marketing (MKT-01–06) and 2026 Ops (OPS-01–09), fifteen numbered function pages plus a 00 Overview page in each. Every page states what the function is for, then separates what is built from what is in testing from what is still open, and names known gaps as content rather than omitting them. The overview pages establish one ownership statement, an ownership map, systems of record (one governing system per data type), technology stack, operating cadence, and dependencies.
Maintenance scripts PATCH pages in place, so hand-edited text and manually set column widths survive automation; house-style passes for punctuation, title case, table cleanup and project sort order run against the live pages. Graph has no page-reorder endpoint, so ordering is achieved by deleting and recreating pages in sequence — documented rather than worked around silently.
Updates
- Aug 21 First pages pushed from the strategy outlines, which carried an explicit working protocol: iterate section by section, ask rather than invent.
- Aug 25 Full nine-page Ops rebuild.
- Aug 26 Overview pages created and an ownership block prepended to every page without disturbing existing content; the Teams billing thread mirrored into the Billing Operations page under a note explaining the source.
In use
Aug 25–27
Visio workflow diagrams and Planner task export
Visio COM · OneNote · Planner
Workflow diagrams are authored by script rather than by hand, via headless Visio automation, with the drawing standard codified in the builder: every shape sits fully inside exactly one lane, cross-lane work is expressed by connectors moving between lanes rather than shapes floating on a boundary, review back-and-forth is drawn as a real loop, and the brand palette and type sizes are fixed. Diagrams are embedded into the OneNote page as an image plus a link to the editable file, since OneNote's API cannot host a live Visio object.
A read-only export then reads the same file as the source of truth: each process shape becomes a task, the lane band its position falls in determines the owner, left-to-right order determines sequence, decision diamonds become checkpoints rather than tasks, and connector data yields real predecessor and successor links including backward loops. Output is a Planner-shaped CSV. Diagram and task list cannot drift apart, because both derive from one file.
A reference architecture document defines the four layers this runs through — source definition, OneNote display, SharePoint data, Planner execution — and inventories nine candidate workflows, each labeled by maturity rather than presented as ready.
2 workflows drawn (video approval, website post) · 15-step task CSV generated from the video approval diagram
Updates
- Aug 31 A second Visio file added for operations, opening with a New Hire Onboarding page drawn to the same conventions as the marketing workflows — strict swimlanes, uniform boxes, brand palette, one shape per Planner task.
- Sep 10 Video Approval page rebuilt with "Request caption from PM" removed, because the Planner gate replaces it: the caption task appearing on the PM's board is the request. Everything else kept, including the revise loop and the parallel color-grade and export branches.
In useThree workflows drawn across two files. The Planner execution layer that consumes them was built Aug 31 — see the task release entries.
Aug 29–31
Website Post task release
Planner · Power Automate · SharePoint
The execution layer underneath the Visio workflows, and the answer to a real problem with putting a multi-step process into Planner: create every task up front and everyone's board fills with work they cannot start yet; create them one at a time and nobody can see what is coming.
Every task in a workflow instance is created up front and parked in a Blocked bucket, unassigned, so it reaches nobody's board. When a task is completed, the flow looks it up in a Workflow Task Sequence list, finds the next step in the same workflow and project, assigns it to its owner and moves it into that project's released column. Assignment is the release mechanism, because Planner's My Tasks only surfaces tasks that carry your name. The sequence lives in a SharePoint list rather than inside the flow, so changing a workflow is a data edit.
Updates
- Aug 29 Website post workflow drawn as page 2 of the Visio file, to the same swimlane conventions as the video approval diagram, and the website page updated.
- Aug 31 Release flow deployed Stopped, for review before it is started.
- Sep 14 Confirmed running: flow state Started against the live tenant.
In useRelease flow Started.
Aug 29
Miro board as a Teams channel tab
Teams · Miro API · Graph
Pins a project's Miro board as a tab on its Teams channel, matching the configuration the Miro Teams app produces except for the board-specific access token, which Miro's public API does not expose. The embed relies on the viewer's own Miro sign-in instead, which is the open question the build exists to answer. Boards are matched by project number with exactly one match required — the script refuses rather than guessing — and it skips any channel that already has a Miro tab.
Updates
- Sep 2 Boards were private to their creator. The tab builder runs on one account's token, and a Miro board created with nothing but a name belongs to whoever created it — so a PM opening the Miro tab in their own project channel hit an access-request screen. Reported by PMs Aug 31. The creation path is fixed, and a separate script opens the boards already out there to the team.
- Sep 2 That repair is deliberately narrow: it touches only boards named exactly like a Teams channel, created after the tab builder's first commit, by the automation's own account. Boards people made by hand are left alone even when they are project-numbered and private, because someone may have meant that and it is not the script's call.
In progressAccess repaired; whether the tokenless embed renders for a signed-in viewer is still what is being tested.
Sep 1–2
Project web-page mockups in Miro
Miro · Figma REST
Website page mockups moved off Figma and onto the Miro project boards, so the mockup sits with the rest of a project's marketing material rather than in a separate tool. A minimal Figma REST client was written first to read the existing files — the REST API works on any plan, whereas the Dev Mode integration is rate-limited on the Starter plan.
The builder generates a page in the firm website's style as a frame on the project's board, with the grid, type scale and block grammar measured off the live site rather than eyeballed: a 1728 container on twelve columns, alternating image-left and image-right rows, paired images sitting side by side rather than stacked, and a fixed type scale. Copy is deliberately left as lorem, because a second script pulls the real paragraphs out of a Miro document widget on the same board and drops them into the frame's text boxes — Miro has no native binding between a document and a frame, so that script is the link: edit the doc, re-run it, the mockup catches up. Text slots are matched by role and width rather than by hard-coded id, so the mapping survives a rebuild, and any shortfall or overflow is reported rather than silently truncated.
In progressBuilt and running against real project boards.
Aug 31
New Hire Onboarding workflow
Visio · Planner · Power Automate
Onboarding drawn as a swimlane workflow in a new operations Visio file, following the conventions set by the marketing diagrams, with one shape per Planner task. Its release flow is the same gate engine built for the website post workflow: every task is created up front and parked unassigned in a Blocked bucket, and completing one assigns the next step to its owner and moves it into the released column.
Updates
- Sep 14 Confirmed running: release flow state Started against the live tenant.
In useRelease flow Started.
Aug 31
Grade template audit and PowerGrade publishing
DaVinci Resolve API · Python
Publishing a grade template only works if the template is genuinely clean, and a node that looks empty in the UI can still carry a power window, a qualifier, a leftover OFX or a LUT. The audit mode prints every node of every clip on a timeline — index, label, and the tools actually present — so a template can be confirmed empty by name before it is published, rather than assumed. The build mode then publishes it as a PowerGrade. Audit is read-only.
Updates
- Sep 3 Defect: the publish step deleted the album's existing stills before grabbing new ones, so a failed grab left the album empty. It now grabs first, checks the count matches the timeline, and stops without deleting anything if it does not.
In useTemplate documentation page published alongside it.
Aug 25 →
Sep 10
Won project setup flow
Power Automate · Teams · Planner · SharePoint
When a pursuit flips to Won, the flow provisions the project: it issues the project number, creates the Teams channel, copies the F-folder structure, moves the proposal files across, deletes the emptied pursuit folder, creates the Planner plan, and stamps the row with a setup status.
Updates
- Aug 25 The flow now issues the next project number itself, using the Teams channel list as the number registry, and resolves the project name from the newest proposal at run time rather than waiting for the overnight sweep, with a fallback so the name is never empty.
- Aug 25 Defect: an early write-back to the row re-triggered the flow, and the re-queued run failed on "channel already exists," recording Failure on a setup that had succeeded. Consolidated to a single write at the end of the run.
- Sep 10 Generic repair for stalled setups. The flow has stalled three times for three different reasons — an Office-locked file on one project, an overnight completion racing a backfill on another, and a file move failing outright on a third. The repair was the same shape each time, so the one-off fix written for the first was generalized: finish the moves, delete the emptied pursuit folder, create the Planner plan, and mark the row Success, in the flow's own order.
In use
Sep 3
Grade sync between timelines
DaVinci Resolve API · Python
Copies clip grades from one timeline to another for the clips that appear on both, so a regraded master does not have to be redone by hand on every cut derived from it. The default run changes nothing: it reports which clips are shared, which source grades exist, which destination clips are already graded, and what it would do. --apply copies the grades; --overwrite is required before it will replace a grade that already exists on the destination.
In use
Sep 10
Carousel slide export from one timeline
DaVinci Resolve API · Python
Renders one file per carousel slide from a single timeline — the equivalent of slicing from guides, for video. Resolve's own individual-clips render cannot do this, because it renders every clip separately, so a slide built from two or three clips comes out as several files. This queues one render job per slide instead.
By default the gaps define the slides: clips that butt together form one slide, and blank frames start the next. Clip markers, where placed, tighten that slide's in or out point. An unmarked timeline therefore splits correctly with no preparation, and marking the one slide that needs a tighter cut does not disturb the others. Alternative modes cover gaps-only and other splits.
In use
Aug 26–28
Outlook follow-up agent
Power Automate · Graph · Outlook
Follows up twice, three days apart, on enrolled emails that go unanswered, written in the sender's own voice with her full signature block embedded in the HTML, since automation-sent mail never picks up the Outlook client signature.
The design decision that matters: the mailbox is the only state. Applying an Outlook category to a sent message enrolls the thread; removing it cancels everything; a reply from the recipient clears it; and the flow's own reply becomes the counter on the next hourly sweep, so nothing needs to be stored. No tracking list, no database, no config UI, and categories are invisible to recipients.
Updates
- Aug 26 Verified in test mode on a synthetic self-addressed thread, both branches passing. Deployment is mode-switched — test points at the operator with a two-minute threshold, production at the real recipient with three days — as an in-place update of one flow rather than a second flow.
- Aug 28 Live defect found and fixed the same day: Graph's reply on your own sent message addresses you, not the original recipients, so the first follow-up went to the sender. Recipients are now set explicitly. The self-addressed test could not have caught this, since sender and target were the same address.
- Aug 31 Incident — hourly runaway, 25 duplicate follow-ups. The flow re-sent the same follow-up on one thread roughly hourly from Aug 28 14:13 to Aug 31 13:13. Root cause: it identified its own messages by matching the sender's SMTP address, but replies it sends store an Exchange legacy DN in that field instead — so it never counted its own sends, and neither the two-send cap nor the three-day clock ever advanced. The second enrolled thread escaped the loop only by accident: its Aug 28 mis-send landed in the sender's own inbox, and that copy did resolve to an SMTP address, so it got counted.
- Aug 31 Incident response: flow stopped, both enrollments cleared, and the sends counted per thread.
- Aug 31 Fix: own-message counting now queries Sent Items for the conversation — folder membership rather than sender matching — so the newest in-thread message is unambiguous. A spacing guard was added on top: a send requires the newest in-thread message to be older than the threshold, which makes more than one send per threshold window structurally impossible even if the counting breaks again.
- Aug 31 Loop-terminator test built against a target that never replies, since the original self-addressed test could not catch this class of bug — the flow's own follow-up matched the replied branch and retired the thread before a third sweep. All six checks passed.
- Aug 31 Standing rule recorded: never use a project or shared mailbox as a test target without explicit approval of that exact mailbox. The loop test put two test messages into a shared project inbox without asking first.
- Sep 2 Checked for any send after the last runaway message before restarting; none found.
- Sep 2 Second follow-up reworded: the first keeps the greeting and thank-you, the second drops both and reads only "Just following up on below," so two identical nudges never arrive.
- Sep 2 Start script added that refuses to start the flow unless the live definition is in production configuration, so it cannot be switched on while still pointed at the test settings.
- Sep 2 Restarted in production. Verified against the live flow on Sep 14: state Started, hourly sweep, three-day threshold, recipients set explicitly on every send.
In useRunning in production since Sep 2, after the Aug 31 fix and loop test.
Aug 20 →
ongoing
Resolve media relink and proxy repair
DaVinci Resolve API · PowerShell · Python
The same August library reorganization that broke InDesign also broke stored clip paths in Resolve. Resolve-Doctor consolidates a dozen single-purpose scripts into one tool the operator runs unattended while on the VPN — which is precisely when the assistant cannot be running, so it had to work standalone with documentation good enough to run without help. Scanning is the default and changes nothing; the fix mode repairs only paths it can confirm exist on disk; every run writes a timestamped CSV. Folder-mapping rules live as editable data at the top of the file, so the next rename costs one line.
The guards are the substance of it. An unmounted drive is not a missing file — without that distinction a fix run with the VPN down would have discarded 136 valid proxy pointers. A clip has two paths, and dead proxy pointers are invisible in Resolve because it silently falls back to the original. Renamed files are never matched by guess; confirmed renames go into a map that starts empty on purpose, and anything ambiguous is reported for a person rather than resolved. The filesystem is re-read after every write, because earlier work reported "21 relinked, 0 failed" while saving nothing. Report verdicts use a graded vocabulary so ambiguous cases route to a human, and rows name the bin, the timelines using the clip, and the timecode of first use written so twelve minutes cannot be misread as twelve seconds.
Updates
- Aug 20 Seed script written, carrying the InDesign relink method across to Resolve with a project-name guard so it refuses to run against the wrong open project.
- Aug 26–27 Consolidated into Resolve-Doctor with scan and fix modes; a companion watcher added because a modal dialog in Resolve freezes the script mid-API-call, making "working hard" and "stopped waiting for a click" look identical from outside.
- Aug 27 Measured that the targeted replace operation works where Resolve's own folder-search relink does not — 40 of 41 versus 11 of 52 on one project. Three renamed overlay clips confirmed by eye and added to the rename map.
- Aug 28 First VPN fix run: 44 confirmed repairs on that project onto real server paths.
- Sep 3 A second project restructured on disk to the standard video template, adding the Video and Audio levels under Temp Videos. The path rules were extended to match, so existing clip paths still resolve after the move.
- Sep 11 Further fix run.
733 clips inventoried · 241 dead proxy pointers surfaced · 136 valid pointers protected from deletion · all 536 remaining offline references traced to the unmounted server, nothing genuinely missing
In progressRepairs continue on VPN runs. One project is relinked through the UI rather than by script, after scripted property reads triggered a codec crash.
Aug 27
Resolve bin and timeline standardization
DaVinci Resolve API · Python
A house bin standard applied across all eight active projects: a canonical order of Timelines, Video, Audio, Graphics, SFX, VFX and Overlays, Compound. Resolve displays bins in creation order and cannot rename or reorder a folder, so the only way to impose an order is to move everything to Master, delete the bins, recreate them in sequence and move the clips back — with the bin-to-clip map written to CSV before anything is touched, so a failed run is recoverable by hand.
Legacy names were normalized to the standard (Footage to Video, VFX to VFX and Overlays, Logo & Texts to Graphics/Logo), an Audio bin with VO, Music and SFX children enforced, loose clips swept in from Master, and an unnecessary codec level flattened out of the Video tree. Timelines were verified to start at 00:00:00:00 and paths checked against the 260-character Windows limit. The bin tree is a fixed template, not a mirror of the folder tree: the folder-mirroring script sorts alphabetically and reproduces folder shapes that do not belong in bins, so it is not used to build them. All projects were exported to .drp beforehand, since a .drp captures bins, timelines, paths and grades whether or not media is online.
Updates
- Sep 8 Video project setup reference written, derived from one project as the correct reference build and cross-checked against another. It records the folder template and the bin template as two different shapes maintained separately; that bins carry no codec level; that five bins have no folder equivalent; and that project-specific bins sit on top of the template. Temp Videos is the working edit store, edited from SharePoint and archived to the server only at end of life, with cross-user path consistency coming from a shared drive mapping over each person's sync folder rather than from moving media to the server.
8 projects standardized · bin map written to CSV before any change · every timeline starts at zero
In useStandard applied across all eight projects and used for new ones; Resolve version upgrade still pending.