A client engaged me to help with cross-project visibility. Their leadership team needed a daily view across multiple parallel workstreams without sitting through a six-meeting standup-of-standups. I built and delivered a starter morning brief system. A Python script reads a STATUS.md file from each project folder, sends the structured data to an LLM with a prompt that forces per-project H2 headings (so quieter workstreams don't get dropped), renders the result to HTML, and ships it to leadership through their existing email infrastructure at 6 AM. The hardest part wasn't the technical build, it was getting the team to actually update STATUS.md at end of session. Solved by promoting the wrap-up step from a passive instruction into a registered action the AI tooling could surface. The whole thing took a weekend, and the client could grow it from there.
The Problem
A client brought me in to help with cross-project visibility. They were running multiple parallel workstreams across the organization. Each one had a separate folder, a separate Jira project, a separate Slack channel, often a separate AWS account, and a completely separate mental model of what was blocked, what was next, and what had a deadline this week.
The failure mode was predictable. Their team leads would finish a deep-focus session on one workstream and get context-switched to another. Several projects later, someone would forget what had been promised for Thursday, or that another stream was waiting on credentials before it could move forward. The context wasn't in anyone's head anymore. It was scattered across Jira tickets, Slack threads, internal documentation, and handwritten notes on a desk somewhere.
Their leadership team wasn't good at remembering to check across all these threads, and that's not a willpower problem. It's an information architecture problem.
So I proposed a morning brief system as a starting point.
The Architecture
The core is simple. A Python script that lives in a shared dashboard folder on their infrastructure. Every morning at 6 AM, Windows Task Scheduler runs it. The script reads a STATUS.md file from each active project folder. Each STATUS.md has YAML frontmatter at the top with structured data (completion percentage, deadline date, blocked_on, next_action, last_updated) and then a markdown body with open items, decisions pending, and deliverables.
The script sends all the project states to an LLM with a precise prompt. The output renders to HTML and ships to the leadership distribution list through their internal email system.
The client already had an email-sending pipeline from another internal project and an Anthropic API key from earlier experimentation. I reused both rather than introducing new services. The whole system took a weekend to build, not a sprint, because the surrounding infrastructure was already there. Tightly coupling new tools to existing infrastructure is a feature, not a bug. It cuts the activation energy of adopting the new thing.
The Constraint That Saved the System
My first version of the prompt was the intuitive one: "give me a 300-word synthesis of what the team needs to know today across all the projects." The model would read all the projects, find the most dramatic ones (a pipeline gone wrong, a cutover week), and silently drop the quieter projects from the output.
That was the problem. Leadership would come into the morning with a brief that made it look like only three real projects were active, and a commitment on one of the missing ones would slip.
The fix: require per-project H2 headings in the output, with at least one bullet per project no matter what. The model can't editorialize anymore. If a project has zero open items that week, it has to say "No blockers, on track." But it has to show up in the output.
That structural change is what made the system actually useful. Without it, the most dramatic projects crowd out the quieter ones, and the quiet projects are where the missed commitments tend to live.
The Hardest Part: End-of-Day Discipline
The technical work was straightforward. The hard part, the part that actually determined whether the system survived the first month, was getting the team to update STATUS.md files at the end of each session. That's where it almost died.
We started with a passive instruction in the team's AI assistant working notes: "If the user says 'wrap' or 'done for the day', update the STATUS.md for this project with current blockers and next actions." Clean, declarative, sitting in documentation where it could be referenced.
It didn't work. Session after session, team members would type "wrap" or "ok let's call it", and the assistant would write a nice conversational summary in chat instead of actually editing the file. The instruction was there, being read, but it was being competed against by the more natural behavior of writing a summary message back to the user.
The fix was to promote this from a passive instruction into a registered action. Now when someone types "wrap" or "status" or "eod" or any phrasing that means "end this session", the action shows up directly in the assistant's available-actions list. Not buried in instructions. Not relying on the model to remember to check the working notes. A visible, structured action that can be invoked.
The general lesson here, applicable to any AI tooling rollout: a CLAUDE.md instruction is probabilistic. The model reads it and might comply, depending on conversation flow, recency, and how strongly its default behavior pulls toward "just respond." A registered action is structurally surfaced in the model's action list every session, which makes invocation much closer to deterministic. If you want an action to happen reliably, give it a structural affordance, not a text instruction.
If you want truly deterministic behavior, you skip the LLM entirely and use rules: a hard-coded check, a workflow gate, an automation that runs regardless of what the model decides. But that's a whole other blog post.
Reliability went from maybe 60% to maybe 85%. Not perfect. People still occasionally forget to type "wrap" at all. But when they do type it, the file actually gets updated. The 6 AM brief reads what was written yesterday at end of day, not stale notes from earlier in the week.
The 6 AM Email
There's something about putting a hard deadline on when leadership is going to face all the commitments that changes behavior across the team. The brief arrives at 6 AM. Before coffee. Before Slack. Before the first meeting.
Leadership reads all the projects' status in two minutes because the format is fixed and the structure is consistent. They know which blockers need escalation, which deadlines are approaching, which projects have been silent for a week and should get attention.
The system isn't about being productive or displaying productivity. It's about not forgetting. It's a commitment artifact. By 6:15 AM the leadership team has already thought about every active workstream. The alternative, opening multiple separate folders, scrolling through Jira, checking Slack, just wasn't happening. The day would start with whatever landed in someone's inbox first and the rest would get remembered or not.
Why Not Notion?
This could have been done with a Notion database, a shared spreadsheet, a Jira dashboard, or any number of SaaS tools.
Reason I didn't recommend that: tight coupling to their existing infrastructure was a feature, not a bug. Their project folders, their STATUS.md convention, their email pipeline, their Anthropic key. The system took a weekend because we didn't have to introduce a new tool or convince anyone on the team to adopt it. It integrated with what they were already using.
If your team would rather a SaaS solution, the same approach works. Pick the tool, define the structure, write the script that aggregates and synthesizes. The structural constraint about per-project visibility is what matters, not the choice of database.
Why Not Subagents?
The natural question when designing an LLM-driven dashboard in 2026 is whether to use a multi-agent setup: a coordinator that fans out to one subagent per project, then synthesizes their outputs into the final brief. It looks elegant on a whiteboard.
I considered it and decided against it. The morning brief is the wrong shape for multi-agent. It's uniform summarization over a small, bounded set of inputs (6 STATUS.md files, each maybe 2-5 KB). A coordinator plus 6 subagents means 7 LLM calls instead of 1, each paying its own system-prompt and framing overhead, plus a synthesis pass to stitch the outputs back together. In earlier testing on a similar workload, I measured that pattern running about 27x more expensive than the single-shot equivalent. The absolute dollars are small (a brief is cheap to begin with) but the ratio is the same and the latency cost compounds too.
Multi-agent earns its cost on a different workload shape:
- Heterogeneous inputs that need different handling. If one project were a Prowler scan dump needing severity sampling, another were a GitHub PR queue needing diff analysis, and another were a raw
STATUS.md, you'd want a different prompt and possibly different tools per source. Here all the inputs share the same shape, so one prompt handles all of them. - Inputs too big for one context. Not this case. The whole brief fits comfortably in a single Sonnet call.
- Independent tool use per source. If each project needed live API calls (Jira, CloudWatch, GitLab) before summarization, parallel subagents would save wall-clock time. But
STATUS.mdis already the cached, condensed view. The fetch-and-condense cost was paid at wrap time.
The interesting design move isn't adding subagents to the brief itself. It's pushing more work into the wrap step, which is where a subagent could legitimately earn its cost. A wrap subagent could pull Jira tickets, recent git history, and CloudWatch alarms for that project, then propose STATUS.md edits before the human confirms. Fan-out at capture time, single-shot synthesis at brief time. That keeps the 6 AM call cheap and fast while making the inputs richer.
What's Next for Them
The biggest gap is that not every project has a STATUS.md yet. The high-stakes ones are fully instrumented. The rest are spotty. If a workstream's STATUS.md is missing or outdated, it doesn't show up in the brief, and leadership loses visibility on it.
The next version we're considering makes STATUS.md generation part of the wrap action itself. When someone wraps a session, instead of just prompting them to manually update the file, the action could scan the session transcript, extract blockers and next actions, and pre-populate the STATUS.md before the human reviews. That closes the gap between "what was done today" and "what got written down."
A more ambitious version of the same idea is the wrap subagent pattern I mentioned above: fan out at capture time to fetch live state from Jira, git, and monitoring before proposing edits. The wrap step gets slower and more expensive (which is fine, it happens once per session and the human is waiting anyway), and the 6 AM brief stays cheap and fast.
For now, the starter system works. Every morning the leadership team gets a brief that tells them what to remember, in a format that doesn't drop projects, sent by email so they can't accidentally skip it. The problem we set out to solve, forgetting commitments across context switches, is solved. Not perfectly, but better than the alternative, which was a six-meeting standup-of-standups that nobody had time for.
Want Help With This?
If you're running a team with multiple parallel workstreams and want to talk through how something like this might apply to your organization, or you've got an existing dashboard that's not getting read, reach out via the contact form. Happy to help.