Operations Framework
Unified meeting and operations processing. Behaviour is driven by org config -- the same skill handles Bravo veckosynk, Acme management meetings, marketing standups, and project dev standups.
Base framework: Extends ops-base -- read ~/.claude/skills/ops-base/SKILL.md for shared standards (meeting formats, task management, workflows, archive policy).
IMPORTANT: The project CLAUDE.md is the single source of truth for vault-specific details. This skill defines the processing workflow; CLAUDE.md defines file locations and naming conventions.
SUBCOMMANDS
status -- Show available configurations
Trigger: /ops status
Parse the user's input. If the first word is status, execute this subcommand instead of the normal processing flow (Steps 1-9).
Steps:
Scan for org configs:
- Find vault root (walk up from CWD until
_inbox/,_outbox/, or.obsidian/; orVAULT_ROOTenv) - Glob
<vault>/*/_ops.yamlfor org-folder configs - Check
<vault>/_config/base.yamlfor vault-wide override - Read and parse each config
- Deprecated fallback: also scan
~/.claude/skills/*-ops-config/for legacy skill-based configs and emit a one-time deprecation warning per session if any are found (removed in v1.17.0)
- Find vault root (walk up from CWD until
Detect active config:
- Check for project-level
.claude/ops-config.yamlin current working directory - Walk up from CWD looking for the nearest
<folder>/_ops.yaml - Determine org from CLAUDE.md
organizationfield or folder name pattern - Report which config would be loaded for the current directory
- Check for project-level
Present report for each org config:
- Organization name, language, swedish_chars
- Team members (name + role, abbreviated if >4 members)
- Workflows: update_files list, action_propagation status, agenda_management status, post_processing status
- Rolling plans: count + axes (if
workflows.rolling_plansconfigured) - Domain additions count
- Summary sections (custom or default TWO-TIER)
- Templates (if configured)
- Strings (custom or default)
Show base defaults from
~/.claude/skills/ops-config/base.yamlVault health check (CR-010
rules.single_inbox_outbox,rules.yaml_naming):- From the detected vault root, scan for stray inbox/outbox directories using the CR-025 fuzzy matcher (same as
/ops sweepcheck 9):_inbox,_outbox,.inbox,.outbox, any*inbox*/*outbox*directory, and localized forms (inkorg*/utkorg*), case-insensitive, skipping.archive//.transcripts//.handoff//clones//node_modules/. Anything other than<vault>/_inboxand<vault>/_outboxis a stray; flag each unless listed inworkflows.sweep.structure_exemptions(exempt paths get a one-line note with their reason). Exact-name matching is not enough -- real-world strays have appeared as.inboxand_outbox-archive. - For every
<vault>/<folder>/_ops.yamlfound in step 1, the folder is treated as ops-aligned. Confirm each parses as YAML; flag any that don't. - List ops-aligned folders that are missing an
_ops.yamlonly when CLAUDE.md or_meta.yamlin that folder declaresorganization-- otherwise the folder is intentionally not ops-aligned and should be silent. - If
~/.claude/skills/acme-ops-config/,~/.claude/skills/bravo-ops-config/, or~/.claude/skills/delta-ops-config/still exists, emit the deprecation warning from step 1 here as a vault-health item too (one-line each, with theunlink/mvcommand to fix). - If everything is clean, print a single
Vault health: OKline. Only expand into a warning list when something is non-conforming.
- From the detected vault root, scan for stray inbox/outbox directories using the CR-025 fuzzy matcher (same as
Output format: Structured markdown report:
## /ops Configuration Status
### Active Config (current directory)
Organization: Acme
Config source: ~/.claude/skills/acme-ops-config/acme.yaml
Project override: none
### Available Organizations
#### Acme
Language: per_claude_md | Swedish chars: strict
Team: Bob (CEO), Carol (COO), Alex (CAIO), +9 more
Workflows:
update_files: summary, changelog, readme, task_matrix, meetings_index
action_propagation: disabled
agenda_management: disabled
post_processing: task_import (enabled), dashboard_refresh (enabled, org: acme)
Domain additions: 8 sections configured
Summary sections: default (TWO-TIER)
Strings: default (per language)
#### Bravo
Language: swedish | Swedish chars: strict
Team: Alex (Affärsutveckling), Hank (CTO)
Workflows:
update_files: summary, changelog
action_propagation: enabled -> BRAVO.md, ALEX.md, HANK.md
agenda_management: enabled -> BRAVO.md / "Nästa veckosynk"
post_processing: disabled
Domain additions: 4 sections configured
Summary sections: default (TWO-TIER)
Templates: meeting_reflection
### Base Defaults
Language: input
Team: (none -- must be defined in org config)
Workflows: summary only
### Vault Health
Vault health: OK
When non-conforming, the Vault Health section expands. Examples:
### Vault Health
- Stray `_inbox/` at acme/_inbox -- contract requires exactly one at vault root. Move contents to <vault>/_inbox/ and remove.
- Missing `_ops.yaml` in <vault>/acme/ -- folder declares `organization: Acme` but has no _ops.yaml. Drop one in or remove the organization declaration.
- Legacy skill `~/.claude/skills/acme-ops-config/` still present (CR-011, removed in v1.17.0). Run `unlink ~/.claude/skills/acme-ops-config`.
help -- Show usage guide
Trigger: /ops help
If the first word is help, present a usage guide instead of processing content.
Include:
- One-line description of what /ops does
- Available commands:
/ops [content],/ops prepare [type],/ops status,/ops normalize <path>,/ops lint <folder>,/ops sweep,/ops help - Skill comparison table: when to use /ops vs /ops prepare vs /transcript, /preparation, /tasks, /daily-dashboard
- Skill connection diagram: how /ops feeds into /tasks, /daily-dashboard, and how /ops prepare creates pre-meeting docs
- Config loading summary (3-line version, point to
/ops statusfor details) - Processing flow summary (9 steps, one line each)
- Common usage patterns (examples including prepare)
Output: Markdown printed directly. No files created.
prepare -- Create pre-meeting preparation
Trigger: /ops prepare [type] [async-updates]
Generate a structured preparation document for an upcoming team meeting. Pulls context from recent meetings, tasks, and optionally incorporates pre-submitted async updates from team members.
Arguments:
type(optional): Meeting type hint (e.g.,standup,war-room,weekly). Default:standupasync-updates(optional): Pre-submitted text updates from team members to incorporate
Examples:
/ops prepare standup
/ops prepare war-room
/ops prepare standup [paste team updates here]
Preparation modes (single vs dual)
The skill supports two preparation modes, configured per meeting type in _ops.yaml under meeting_types[<type>].preparation_mode:
| Mode | When to use | Files produced | Filename pattern |
|---|---|---|---|
single (default) |
1-on-1s, marketing meetings, anything where the facilitator and the participants are the same audience or there is no sensitive facilitator-only content | One file | YYMMDD-preparation-[context]-[type].md (or förberedelse for Swedish) |
dual |
Group meetings (standups, weeklies, war rooms) where the facilitator needs a private layer (deflection strategies, time-boxing cues, sensitive probes, policy reminders that should NOT be visible to attendees) on top of the normal team-facing prep | Two files | YYMMDD-agenda-[context]-[type].md (visible to team -- the standard prep) + YYMMDD-facilitator-[context]-[type].md (private add-on layer) |
Default is single -- only opt into dual when the org explicitly configures a meeting type to need it. If no meeting_types config exists, fall back to single regardless of type argument.
Dual mode -- two-layer model:
The agenda file is the team-facing prep document. It looks like the prior-day prep file in that folder -- same shape, same sections, same level of detail. The facilitator file is a separate private layer that contains only the additional content the facilitator needs and the team should not see.
Agenda file (visible to all attendees) -- mirror the prior-day single-mode prep in the same folder:
- Status overview (per-person yesterday/done/today)
- Key updates from async chat or prior meetings
- Async updates verbatim (if any)
- Agenda items with owners and time-boxes
- Blockers table, decisions pending, open action items carry-forward
- Reference links, build status, metrics
- Anything participants need to come prepared
Facilitator file (private, NOT shared with the team) -- contains only the additional layer:
- Facilitator's role clarification (e.g., "Alex runs the meeting only -- not driving test or fix work")
- The lead's expectations from prior handover or 1-on-1s
- Time-box discipline cues ("standup has run 25 min recently, target 30, hard stop 35")
- "Watch for" cues during the meeting (e.g., "Dana defaulting to 'I'll check after standup' on R2 blockers -- push for concrete commitment now")
- "Things NOT to surface in this forum" list (vertical/board topics, personnel matters, etc.)
- Decisions the facilitator owns and the framing for each (esp. when filling in for someone)
- Post-standup follow-ups the facilitator drives
- Pre-meeting backstory from 1-on-1s or lunches with subset of attendees
Critical rule: the agenda file does NOT mention or hint at the facilitator file. The visible document must not advertise that a private one exists. Cross-references go from facilitator → agenda only, not the other direction.
Critical rule: if the same content fits both files, it goes in the agenda file. The facilitator file should only contain content that would change behaviour or expose sensitive context if shared with the team.
Step P1: Gather Context
- Load org config (same as normal /ops flow)
- Read recent meetings:
- Find last 1-3 meeting summaries in the target folder
- Extract action items assigned to each team member
- Note decisions made, blockers identified
- Read the task ledger (resolve
workflows.task_ledgerfirst -- see ops-base, CR-040):local: pull active tasks per person from_tasks.yaml(status: pending, in_progress, blocked)external: read the declaredpointerif it is reachable; otherwise state in the prep that open work lives insystemand was not read. Never fall back to an ancestor_tasks.yaml- Identify blockers and their owners
- Read CHANGELOG.md:
- Scan recent entries for context
- Triage scan (CR-022): if the vault has a registered triage doc (
_inbox/working document,type: working_doc+ tagdo-not-process), pull open bullets whose bracket-tag second segment resolves to this meeting's participants ([Möte · X],[Uppföljning · X], ...) into the prep's agenda/open-actions, and stamp each pulled bullet→ i prep YYMMDD-- the only write allowed to the triage doc (same rule as/preparationStep 2.4). Skip silently when no doc or no matches.
Step P2: Parse Async Updates (if provided)
If the user provides pre-submitted team updates:
- Identify team members using the name resolution algorithm:
- Match against org config
team[](name, aliases) - Match against
_contacts/*/_meta.yaml(display_name, aliases) for external contacts - Matching is case-insensitive with Swedish character folding
- See Contact Metadata Schema
- Match against org config
- Extract per-person updates:
- What they report as done
- What they're working on today
- Issues/blockers mentioned
- Decisions or announcements
- Correlate with yesterday's tasks:
- Match reported items against action items from previous meeting
- Determine status: DONE, IN PROGRESS, NOT STARTED, NO UPDATE
Step P3: Generate Preparation Document
Create the file using the Standup Preparation Template:
# [Organization/Project] [Meeting Type] -- [DD] [Month] [YYYY]
**[Next event note if relevant, e.g., "War room tomorrow: Wednesday March 12, 10:00-12:00 CET"]**
---
## Status Overview
| Person | Yesterday | Done | Today |
|--------|-----------|------|-------|
| **[Name]** | [Tasks assigned] | [What's done] | [Today's plan] |
| ... | ... | ... | ... |
**[Key metric if relevant, e.g., "Test results: 4 PASS / 4 FAIL (50%)"]**
---
## Key Updates
| Update | Source |
|--------|--------|
| [Important update or decision] | [Person] |
| ... | ... |
---
## Agenda
- [ ] 1. **[Person]** -- [Key questions]
- [ ] 2. **[Person]** -- [Key questions]
- [ ] ...
- [ ] N. **[Topic]** -- [Confirm/discuss]
---
## Reported Updates
**[Person]:**
> "[Their exact update text]"
**[Person]:**
> "[Their exact update text]"
...
---
## Blockers
| Issue | Status | Owner |
|-------|--------|-------|
| [Blocker description] | [Status] | [Owner] |
| ... | ... | ... |
---
## Decisions
**Made:**
- [Decision] -- [brief rationale]
**Pending:**
- [Decision needed]
---
# Reference
## [Relevant reference section, e.g., Test Results]
[Tables or details as needed]
## Builds / Versions
- [Current build info]
---
*Created: [YYYY-MM-DD]*
Step P4: Template Variations
For standup:
- Focus on Status Overview (Yesterday → Done → Today)
- Keep agenda person-by-person
- Include reported updates if async input provided
For war-room:
- Add "Focus Areas" section after agenda
- Include test matrix reference
- Add "Participants" confirmation
For weekly/planning:
- Add "Sprint Goals" or "Week Priorities" section
- Include metrics summary
- Add "Carry-over Items" from previous week
Step P5: Save and Report
Resolve preparation mode:
- Look up
meeting_types[<type>].preparation_modein the merged org config - If absent, default to
single
- Look up
Determine filename(s):
Single mode -- one file:
- Format:
YYMMDD-preparation-[org/project]-[type].md(English) orYYMMDD-förberedelse-[org/project]-[type].md(Swedish) - Include the organization or project name to distinguish preparations created the same day for different orgs/projects
- Examples:
260311-preparation-acme-mobile-daily-standup.md,260311-förberedelse-delta-veckosynk.md
Dual mode -- two files (always English -- dual mode is not yet localized for Swedish):
- Agenda file (team-facing):
YYMMDD-agenda-[org/project]-[type].md - Facilitator file (private add-on layer):
YYMMDD-facilitator-[org/project]-[type].md - Examples:
260505-agenda-coreteam-weekly-w19.md+260505-facilitator-coreteam-weekly-w19.md
Order of generation: write the agenda file first using the same template the same folder's prior-day single-mode prep used (status overview, blockers, action items, agenda, references). Then derive the facilitator file as a slim private layer on top -- only the content from the "Facilitator file" list above. If a section is present in both, keep it in the agenda and remove it from the facilitator file.
- Format:
Save to meetings folder (per CLAUDE.md MEETING ROUTING). For dual mode, both files go in the same folder.
For dual mode, ensure the cross-references are one-directional:
- The facilitator file MUST link to the agenda file at the top with a notice such as:
> **Private facilitator file.** The team-facing version is [YYMMDD-agenda-...md](YYMMDD-agenda-...md). Do not share this file with the team. - The agenda file MUST NOT mention or link to the facilitator file. The visible document must not advertise that a private one exists.
- The facilitator file MUST link to the agenda file at the top with a notice such as:
Report what was created:
Single mode:
Created: meetings/260311-preparation-acme-mobile-daily-standup.md Status Overview: - Dev1: 1 done, 4 in progress - ... Blockers: 4 items Agenda: 7 itemsDual mode:
Created (dual mode): - meetings/coreteam/260505-agenda-coreteam-weekly-w19.md (team-facing -- full prep) - meetings/coreteam/260505-facilitator-coreteam-weekly-w19.md (private add-on layer) Agenda file: status overview (8 people), 10 agenda items, 6 P0 blockers, 13 carry-forward actions Facilitator-only layer: 5 items (role clarification, time-box cues, "watch for" list, "do not surface" list, post-meeting follow-ups)
Step P6: Lifecycle
After the meeting, when /ops [transcript] is run:
- Single mode: the
preparation/förberedelsefile is automatically marked as superseded (per Step 9 of normal flow) - Dual mode: BOTH the
facilitatorandagendafiles are marked as superseded - No manual action needed
Notes
- No CHANGELOG update for preparation files (they're pre-meeting)
- Language: Follow same rules as normal /ops (per_claude_md, etc.)
- If no async updates provided: Generate preparation from historical context only, with empty "Reported Updates" section or skip it
- If team member missing from updates: Show "No update" in Status Overview
normalize -- Restore Swedish characters in hand-written docs (CR-007)
Trigger: /ops normalize <path> [--dry-run] [--strict-no-ambiguous]
Lint pass that scans markdown and YAML files for known Swedish character drift (ar → är, for → för, pa → på, mote → möte, etc.) and restores the correct characters. Use it on hand-written ops documents that bypassed the /transcript and /ops pipelines and accumulated character errors.
Use cases:
- A folder of pasted notes (e.g.,
_projects/<client>/ops/*.md) was created without going through/opsand never got a Swedish-character pass - A legacy file from before CR-007 inheritance was added still contains old drift
- Bulk remediation across a sub-tree
Arguments:
| Argument | Meaning |
|---|---|
<path> |
A single file OR a folder. If a folder, scans all .md and .yaml files recursively. |
--dry-run |
Show the diff without writing. Use to preview before applying. |
--strict-no-ambiguous |
Skip substitutions marked ambiguous: true in swedish_substitutions.yaml (e.g., ar → är, bor → bör, Andre → André). Recommended for first-pass scans. |
--names |
(CR-017) Instead of Swedish characters, normalize person names: apply the org people[] roster (aliases → canonical) across the target's .md files and CHANGELOG. Reports each substitution for confirmation before writing; never runs implicitly. |
--filenames |
(CR-021) Instead of file content, normalize filenames against the slug contract (restore å/ä/ö, fix digit-transliterations like m0te, unify date prefix to YYMMDD). Dry-run lists old → new; on apply, renames AND updates inbound references found in the same tree (CHANGELOG.md, README.md, supersede stamps, wikilinks). |
Examples:
/ops normalize _projects/bravo-project/ops/annonsering.md
/ops normalize _projects/bravo-project/ --dry-run
/ops normalize _projects/bravo-project/_insights.yaml --strict-no-ambiguous
Step N1: Load substitution map
Read ~/.claude/skills/ops-config/swedish_substitutions.yaml. This file contains the seed substitution list (from MEMORY.md) and is the single source of truth for the linter.
Step N2: Scan target file(s)
For each file:
- Detect language. Treat the file as Swedish-context if any of:
- The file already contains å, ä, or ö characters
- The file is in a folder configured for Swedish (per CLAUDE.md or
language_inheritancein base.yaml) - The user explicitly passed
--lang sv
- Skip if not Swedish-context -- this is a Swedish-character normaliser, nothing else
- Tokenize the file while preserving:
- Code blocks (
...) -- skip - Inline code (
...) -- skip - URLs and file paths -- skip
- YAML keys (only
value:parts are scanned, not keys) -- skip keys - Lines containing
<!-- no-normalize -->-- skip the entire line
- Code blocks (
- For each token, look up against the substitution map. Use word-boundary matching (
\bword\b). - Skip ambiguous substitutions if
--strict-no-ambiguousis set.
Step N3: Apply or report
If --dry-run:
- Print a unified diff to stdout showing all proposed substitutions
- Print a summary: total substitutions, ambiguous skipped, files affected
- Do not write anything
If not dry-run:
Apply substitutions to each file
Write the file back atomically (write to temp, rename)
Update or create a
CHANGELOG.mdentry in the file's parent folder (if a CHANGELOG exists):- **YYMMDD: Normalize** [filename] -- restored Swedish characters (N substitutions). -> [file]
Step N4: Report
Normalized 4 files, 23 substitutions applied:
_projects/bravo-project/_insights.yaml 8 substitutions
_projects/bravo-project/ops/annonsering.md 7 substitutions
_projects/bravo-project/ops/byrasamarbete.md 5 substitutions
_projects/bravo-project/ops/c56-krav.md 3 substitutions
Ambiguous substitutions skipped (use without --strict-no-ambiguous to apply):
ar -> är: 14 occurrences
bor -> bör: 2 occurrences
Backup: none (use git to revert if needed)
Notes
- No backup files written. Rely on git for revert. If the target is not a git repo, the user is warned and asked to confirm.
- The substitution list is data, not code. New common drifts can be added to
swedish_substitutions.yamlwithout changing skill code. - Defence in depth: the same substitution map is used by
/insightspre-write validation (see insights/SKILL.md). The normaliser is the after-the-fact remediation; the validator is the at-write-time gate.
lint -- Check existing files against template contracts (CR-018)
Trigger: /ops lint <folder>
Read-only version of the CR-018 pre-save template-contract check, run across a folder's existing files. Use it to detect template forking in a recurring series -- the drift class where each file is internally consistent but the series silently changed shape at some point.
Steps:
- Resolve the contract registry (
workflows.meeting_templatesfrom the merged config;default= CR-006 canonical). - For each
YYMMDD-*.mdmeeting summary in the folder (skip preps, agendas, emails,.archive/): resolve its contract bymatchglob and run the three checks (heading sequence, action-table header row, empty-Beslut marker). - Group findings by series and by first-deviating date -- the output should read "this series forked at YYMMDD", not a flat per-file list:
/ops lint meetings/management
weekly-management (14 files checked):
OK through 260519. Forked at 260526:
- action_table: missing column "Prio" (260526, 260605, 260702 -- 3 files)
- heading "Sammanfattning" (banished) prepended (same 3 files)
1-on-1 files (22 checked): all OK.
To accept the new shape: declare it in workflows.meeting_templates.
To fix the files: edit manually or re-run /ops on the source transcripts.
- Never rewrites files. Lint reports; the user decides between amending the contract (accept the fork as deliberate) and fixing the files.
sweep -- Closure/staleness audit (CR-019)
Trigger: /ops sweep [scope] (default scope: vault root; depth 6; skip .archive/, .transcripts/, .handoff/, clones/, node_modules/, .ephemeral/)
Skills append reliably but never reconcile: indexes lag, ledgers rot, migrations leave live-looking corpses, sent outbox items never get archived. Bookkeeping follows attention, not structure -- so nothing catches the abandoned lane until a human stumbles on it. /ops sweep is the missing sweeper: one read-only pass that detects the closure-debt classes and offers fixes (report-only by default; every fix is confirmed, never automatic).
The nine checks:
- Index lag -- README.md / meetings/README.md whose newest referenced date lags the folder's newest
YYMMDD-*file or CHANGELOG head entry by >14 days. CHANGELOGs are the heartbeat; READMEs are the lag indicator -- compare them per folder. - Ledger rot --
_tasks.yamlwith open tasks whoselast_updatedlags folder activity by >30 days;_insights.yamlwhoselast_compiledstamp is absent or >30 days older than its newest entry (compile never ran / is stale). Resolve the ledger mode first (CR-041). Readworkflows.task_ledger.modebefore judging a missing_tasks.yaml:local(default): as above, unchanged.external: the rot check is skipped and replaced by two others -- (a) incoherent declaration:systemorpointerabsent, or the pointer unresolvable; that is the real failure mode for this shape, and it is silent otherwise. (b) The duplicate the declaration exists to prevent: a folder declaringexternalthat nonetheless contains a_tasks.yaml. Report both as findings with the same weight as rot.none: skip._insights.yamlstaleness is checked in every mode -- the knowledge layer is local regardless of where the work is tracked. Rationale worth keeping in the report: a declared absence is deliberate, an undeclared one is indistinguishable from neglect. Reporting a correctly-configured folder as broken every week is worse than not checking it -- the first time the sweep is right and nobody believes it, the check has stopped working.
- Migration corpses -- artifacts that look live but were superseded by a move: root symlinks/files whose same-purpose counterpart elsewhere is fresher (dashboards,
_TODAY-*); folders inactive >60 days whose participant/topic stream demonstrably continues in a sibling folder. Offered fix: a tombstone (see ops-base Retirement Convention). - Outbox aging -- run the
/outbox listlogic: sent-but-unarchived items, manifest-less items, manifests missingKanonisk källa(CR-032), and items pending >30 days. Offered fix:/outbox archive --all-sent. TheKanonisk källafinding matters because without it nobody can tell whether a folder is a disposable rendering or the only copy of the material -- which is what made a bulk clean-up unsafe in the 260828 audit (86 items, 3 of 71 manifests named a source). - Sync duplicates --
* 2.*/* 3.*files whose base file exists. Report size+mtime comparison side by side; never auto-delete (the larger "duplicate" is sometimes the newer content). - Unrouted residue --
unsorted/folders with files >30 days old;.ephemeral/content >14 days old; root-level files matching paste conventions (__*,xxx -*,Namnlös*, untitled). - Triage hygiene (CR-022) -- if a triage doc is registered: INKORG items unsorted >7 days,
[x]items not yet moved to the KLART archive, week anchor >7 days stale, plaintext-credential-looking lines (no-secrets rule; lines marked<!-- secret-ok -->are a recorded owner decision and are skipped). Offered fix:/inbox triage refresh(which handles all but the sorting -- that stays human). - Contract alignment & repo privacy (CR-023/CR-029) -- if
workflows.sweep.alignment_check.commandand/orworkflows.sweep.privacy_scan.commandare configured (maintainer machines only; absent → skip silently): run each command (read-only by construction) and parse its[OK]/[DRIFT]/[FINDING]/[SKIP]verdict lines. The privacy scan watches the whole public-repo tree continuously — denylist identifiers, secret patterns, and name-like tokens missing from the invented-examples allowlist — so a leak that somehow lands is caught within a week, not at the next audit. Report each[DRIFT]component with expected-vs-actual version and a pointer to the update runbook (documented in the alignment script's header).[SKIP]is reported as unverified, not clean -- an unreachable component (e.g. a stale mount) is itself a finding, and has previously hidden six releases of drift. Never auto-applies fixes: cross-repo version references and live deploys are human-confirmed changes. The alignment command stays the single source of truth for the component list; the sweep is the scheduled reader that guarantees its output is actually seen. - Structure conformance (CR-025) -- enforce the CR-010 single-inbox/outbox rule with a fuzzy matcher, because reality drifts through variants that exact-name checks miss: scan for directories matching
_inbox,_outbox,.inbox,.outbox, any*inbox*/*outbox*, and localized forms (inkorg*/utkorg*), case-insensitive. Everything except the vault-root_inbox/+_outbox/pair is a finding -- including empty scaffolds (they re-seed the habit). Paths inworkflows.sweep.structure_exemptionsare skipped with a one-line(exempt: <path> -- <reason>)note: deliberate exceptions are recorded once and respected. Offered fixes (never auto-applied): merge pending items into the central folder via the normal/inbox//outboxflows so manifests and indexes stay true; archive already-resolved material to its destination folder; delete empty scaffolds; or add astructure_exemptionsentry if the exception is deliberate. Rationale worth repeating in the report: a second outbox means the central pending list lies.
Output: one report grouped by class, each finding with its offered fix as a command or concrete action. End with a one-line scoreboard (9 classes: 5 clean, 3 with findings (14 items), 1 skipped) so repeat runs are comparable. Young folders are exempt via the age thresholds -- a fresh project reports nothing.
Wiring: suitable for a weekly scheduled run that drops its report into _inbox/ as a triage item (closing the loop through the existing daily-triage habit). The sweep itself never mutates content.
WHEN TO USE /OPS vs /OPS PREPARE vs /TRANSCRIPT
/ops prepare: Use before a team meeting to create a structured preparation with status tracking. Pulls context from recent meetings and tasks. Optionally incorporates pre-submitted async updates from team members. Outputs one file (preparation/förberedelse) by default, or two files (facilitator+agenda) when the meeting type is configuredpreparation_mode: dual./ops: Use after a meeting to process content into structured documentation (summary, changelog, README, task matrix, meetings index, task import, dashboard). Recommended default for all org meetings. Automatically marks any preparation file as superseded./transcript: Use for ad-hoc recordings, personal calls, or contexts without an ops config. Produces summary + changelog + optional task import only.
Flow:
/ops prepare standup → creates preparation (before meeting)
[meeting happens]
/ops [transcript] → creates summary, marks prep as superseded (after meeting)
When /ops and /transcript both apply, prefer /ops -- it is a superset of /transcript functionality.
CONFIGURATION
Config Loading
- Determine organization from:
- Explicit
organizationfield in project CLAUDE.md - Project folder name pattern (e.g.,
bravo-*-> bravo,acme-*-> acme) - Participant names matching team members in configs
- Explicit
- Load config following resolution order:
- Project-level:
.claude/ops-config.yaml - Folder-local (CR-011): nearest
<folder>/_ops.yamlwalking up from CWD until vault root - Vault-wide (CR-011, optional):
<vault-root>/_config/base.yaml - Skill defaults:
~/.claude/skills/ops-config/base.yaml - Deprecated fallback (removed v1.17.0):
~/.claude/skills/{org}-ops-config/{org}.yaml
- Project-level:
- Merge layers -- project overrides folder-local, folder-local overrides vault-wide, vault-wide overrides skill defaults
What Config Controls
| Setting | Effect |
|---|---|
language |
Output language (english/swedish/input/per_claude_md) |
swedish_chars |
Swedish character enforcement (strict) |
team |
Participant recognition and attribution |
responsibility_matrix |
Owner assignments |
terminology |
Domain-specific terms |
summary_sections |
Custom summary structure (overrides TWO-TIER) |
status_terminology |
Domain-specific status terms |
issue_id_format |
Issue ID pattern |
workflows.update_files |
Which files to update |
workflows.action_propagation |
Propagate actions to external files |
workflows.agenda_management |
Post-meeting agenda updates |
meeting_types[<type>].preparation_mode |
single (default) or dual -- whether /ops prepare produces one file or a facilitator/agenda pair |
workflows.meeting_templates |
Per-meeting-type shape contracts + lint mode (warn/strict) -- see ops-base Template Contracts (CR-018) |
workflows.post_processing |
Task import, dashboard refresh, and optional priorities artifact (priorities_artifact.enabled) after meeting |
workflows.rolling_plans |
Participant-triggered per-axis living planning docs (update after a matching 1-on-1) |
domain_additions |
Extra sections to add to summaries |
templates |
Custom template paths |
strings |
i18n string overrides |
PROCESSING FLOW
Step 0.5: Load Applicable Rules (CR-013)
Before parsing the input, load any promoted rules from the _insights.yaml chain in scope:
- Walk up from CWD collecting
_insights.yamlfiles at each level (max depth 6, skip.archive/,.handoff/,clones/). - Filter to rules: entries where
confidence: ruleANDstatus: active. - Cap to 20 entries — if more, prefer highest
confirmation_count, ties broken by most recent confirmation date. - Build a one-line-per-rule preamble in the form
[type] summaryand treat it as additional standing instructions for this run. For example:[preference] Bob prefers concise weekly summaries[pattern] Bob raises customer-success topics last in 1-on-1s[decision] Board updates use English for India team
- Apply the rules during Step 3 (Create Meeting Summary) and Step 4 (Apply Domain Additions). Do not echo the preamble in the output; rules influence content, not chrome.
Scoping: Only rules in the CWD's parent chain apply. A rule in meetings/marketing/_insights.yaml is not loaded when running /ops from meetings/management/.
No rules found: Skip silently. The skill works without rules; this is purely additive context.
Step 1: Parse Input
Extract from the input (transcript, notes, standup content):
- Participants and their roles -- use name resolution algorithm:
- Match against org config
people[]roster (canonical, aliases) for recurring non-contact persons (CR-017) - Match against org config
team[](name, aliases) for internal team - Match against
_contacts/*/_meta.yaml(display_name, aliases) for external contacts - Use resolved canonical names in output (correct spelling, Swedish characters)
- Committed-spelling consistency (CR-017): before saving the summary AND before writing CHANGELOG/README entries, run the folder-precedent near-miss check from
/transcript("Committed-spelling consistency" section) -- compare draft names and anomalous proper nouns against the target folder's recent files and CHANGELOG; use the established spelling when it resolves, flag both forms when it doesn't, never silently introduce a spelling variant. CHANGELOGs are how misspellings propagate; this check gates them too.
- Match against org config
- Completed work items (who did what)
- In-progress work (current status)
- Decisions made (with rationale)
- Action items (with owners and deadlines)
- Issues/blockers discovered
- Technical updates
- Version/build information (if mentioned)
- Metrics and KPIs (if mentioned)
Step 2: Determine Summary Format
If summary_sections is defined in config (non-empty list):
Use the configured section structure. Each section becomes a numbered heading with the specified type (table/subsections/freeform). Only include sections whose trigger condition is met.
If summary_sections is empty or not defined:
Use the TWO-TIER SUMMARY FORMAT from CLAUDE.md:
- Concise Operational for weekly syncs, quick calls, standups
- Detailed Strategic for quarterly reviews, major decisions, milestones
Step 3: Create Meeting Summary
- Determine date from transcript/content or use today
- Determine filename and location from CLAUDE.md MEETING ROUTING
- Build summary using the format from Step 2
- Include metadata header (date, time, participants, format)
- Write executive summary (2-3 sentences)
- Populate all applicable sections
- Attribute actions to correct people using
responsibility_matrix
Step 4: Apply Domain Additions
For each entry in domain_additions from config:
trigger: always-- always include the sectiontrigger: if_mentioned-- include if the topic appears in the inputtrigger: if_relevant-- include if contextually appropriate
Append domain-specific sections after the standard summary structure.
Step 5: Update Files
Update files per workflows.update_files from config:
| File key | Target | Action |
|---|---|---|
summary |
Meeting summary | Always created (Step 3) |
changelog |
CHANGELOG.md | Add dated entry at top |
readme |
README.md | Update Current Status, Active Tasks, Recent Meetings |
task_yaml |
_tasks.yaml | Update/create per-folder task file (v2 schema). Skipped entirely when workflows.task_ledger.mode is not local (CR-040) |
meetings_index |
meetings/README.md | Add entry to meeting index |
For changelog, follow the format in ops-base. Always reference the meeting summary file.
Step 5.5: Knowledge Extraction (silent)
After updating files, scan the meeting summary for durable insights worth accumulating. This step writes to _insights.yaml in the same folder as the CHANGELOG -- it is a silent accumulation layer that never surfaces in any skill output.
Same extraction logic as /transcript Step 3.5 (insight types, threshold, format, dedup). See the transcript skill for the full _insights.yaml schema and extraction criteria.
Reusability (CR-020): Names are allowed in insight entries (the former no-names privacy rule is retired). Prefer name-free phrasing in summary/tags when the insight generalizes -- context and source.file carry the who/what; names in rationale are always fine. Apply the write-time vocabulary guard from /transcript Step 3.5 (canonical types only, confidence = hypothesis|rule, YYMMDD dates, integer ids, max 5 tags).
Swedish characters: When writing Swedish content in _insights.yaml, ALL words MUST use correct å, ä, ö. YAML files are equally prone to missing characters.
Additional ops-specific sources:
- Strategic decisions from
domain_additions->decisiontype - Cleared agenda items with resolution ->
learningordecisiontype - Configuration or workflow changes discussed ->
decisiontype
Process:
- Scan the meeting summary (including domain addition sections) for qualifying insights
- Write to
_insights.yamlin the same folder as the CHANGELOG - Dedup by
source.file-- if insights from this meeting file already exist, skip
Skip conditions:
- No CHANGELOG.md in the target folder
- Pure standup (short status updates without decisions)
- User explicitly said "skip insights"
Output: Same brief format as transcript Step 3.5:
Extracted [N] insights to _insights.yaml:
- [type] summary sentence
Step 6: Propagate Actions
If workflows.action_propagation.enabled is true:
- Decisions ->
targets.decisionsfile - Per-person actions ->
targets.actions_by_person.{name}file
Step 7: Manage Agenda
If workflows.agenda_management.enabled is true:
- Open the file at `agenda_management.fi
…(truncated)