Install
openclaw skills install @vmishra-atlassian/brief-engineeringTechnical daily brief for engineers: service health, deploys, alerts, DLQ/latency, workflows, migrations, customer signals. Use for engineering/on-call briefs.
openclaw skills install @vmishra-atlassian/brief-engineeringA technical morning brief for engineers, on-call responders, EMs and PMs. It answers one question: what about my services is broken, degrading, or about to bite me today?
This is not brief-today. That skill covers personal work — assigned tickets, PR
reviews, calendar, mentions. This one covers service and system health and
deliberately suppresses routine personal work items.
cronbrief-todayplan-dayEverything runs inside the invoking user's RovoClaw workspace using that user's delegated access. There is no shared service account, stored token or credential in this skill.
No browser permissions are required or requested: no tabs, no history, no page content, no personal DMs.
Verify the schema before trusting a result. A tool can return HTTP 200 and still
have ignored your input. Compass component_search takes queryString; passing
query returns every component in the instance — 88,539 rows that look like a valid
response. Run is tools schema <tool> first, match parameter names exactly, and
sanity-check result counts against what you expected.
Read the error before blaming the platform. Failures look alike but are not.
| Symptom | Cause | Action |
|---|---|---|
exit 1 MCP_TOOL_CONFIGURATION_INVALID_INPUT | usually a missing required argument | check is tools schema, supply every * field, then retry |
exit 1 MCP_SERVER_REGISTRATION_PERMISSION_DENIED | server not granted to this principal | access request, not a bug report |
exit 1 MCP_TOOL_EXECUTION_SERVER_NOT_FOUND | backing server not deployed | nothing to do; report as unavailable |
| exit 2 | OAuth consent missing | surface the link once, stop |
not found on requested MCP surfaces | tool does not exist here | enumerate with is tools list --filter <x> --one-line |
Four tools first recorded as broken were missing or misnamed arguments, not platform faults. Only declare a platform fault after the schema is fully satisfied.
The published schema is not always right. get_suggested_resources_by_key
advertises issueKeyOrId but the server demands incidentIdOrKey. When the schema and
the runtime error disagree, trust the error text — it names the parameter the server
actually wants.
TZ=<user-tz> date '+%Y-%m-%d %H:%M %Z %A'
Read USER.md for timezone and role. Then read
memory/engineering-brief/scope.json — that file is the only source of service
names. Never hardcode a service, team or project into a prompt, a schedule or this
skill. If the brief mentions a service that is not in scope.json, the run is wrong.
If scope.json is missing, or reconfirmDue has passed, rediscover and confirm before
briefing:
twg work query --scope me --since 14d
is tools call compass_compass_atlassian_component_search \
--cloud-id "$ATLASSIAN_CLOUD_ID" \
--args '{"queryString":"<repo-or-service-prefix from the work query>","includeOnCallSchedules":true,"includeDependsOn":true,"includeCustomFields":true}'
Keep components where typeId is SERVICE and the owning team matches the user's.
Exclude LIBRARY, OTHER and anything suffixed -archetype. Where two components
share a name, prefer the owned SERVICE and record the duplicate as excluded.
Read the platform, owner and business-unit custom fields while you are there. A
service with no platform value is unregistered, which is why its deploy state comes
back empty — that is a finding, not a broken connector.
Present the candidates and ask the user to confirm once. Then write scope.json:
{
"schemaVersion": 1,
"confirmedAt": "<iso8601>",
"user": { "accountId": "...", "persona": "engineer", "timezone": "..." },
"team": { "displayName": "<from compass ownerTeam>" },
"services": [
{ "name": "...", "componentId": "...", "platform": "micros",
"owner": "someone@atlassian.com", "spinnaker": true }
],
"excluded": [ { "name": "...", "reason": "..." } ],
"projects": ["..."],
"signalPacks": [],
"operationalRelay": {
"url": "<optional creator-private Confluence live document>",
"maxAgeMinutes": 90
},
"reconfirmDue": "<iso8601, about 90 days out>"
}
Storing owner per service is what lets a recommended fix name a real person instead
of saying "the team should".
Activity is not ownership. Touching a repo does not make the user an owner of its service. Only Compass ownership plus explicit user confirmation establishes scope.
Resolve the team from identity, not from service metadata. Three different things look like "the team" and they disagree:
| Source | What it actually means |
|---|---|
atlassian_team_..._team_search with verified membership | the user's real team |
Compass ownerTeam on a component | who owns that component |
opsgenie_team in production.sre_incident.service | who gets paged for that service |
A service can be owned by one team and paged to another. Expanding scope from
opsgenie_team pulls in every service sharing that paging rota — on one test that
turned 4 services into 16, most belonging to other people.
Resolve the team like this:
twg org-tree # manager chain
is tools call atlassian_team_atlassian_team_atlassian_team_search \
--cloud-id "$ATLASSIAN_CLOUD_ID" \
--args '{"organizationId":"ari:cloud:platform::org/<uuid>","query":"<team name>","first":5,"membersFirst":60}'
Confirm the user appears in members.edges[].node.member. Record the paging team
separately under alertRouting — useful for alert queries, never a source of scope.
When the user states their scope, that is final. Discovery proposes; the user decides. Do not re-expand a confirmed scope on a later run because a query surfaced adjacent services.
See references/signal-packs.md for the team config contract.
Run these in parallel. Bound every call. Record which succeeded — coverage reporting
depends on it. Full inventory with verified status in references/signal-catalog.md.
The brief is useless if it only reports infrastructure. Collect what the engineer is actually being measured on.
# everything assigned and open, newest first
twg jira workitem query --jql "assignee = currentUser() AND statusCategory != Done ORDER BY updated DESC" --limit 25
# just this sprint, grouped by status
twg jira workitem query --jql "assignee = currentUser() AND sprint in openSprints() AND statusCategory != Done ORDER BY status" --limit 30
# PRs I authored and PRs waiting on my review
twg pull-requests query --limit 25
Rows land under data.issues and data.pullRequests. Sprint sits in
customfield_11880 as a list, so read [0].name.
Three things matter more than the raw list:
Spec In Progress and one In Progress
is a finding, not a backlog. Say it plainly: the sprint has not started moving.In Review needs a nudge, not a plan. Surface
it above anything still in spec.Add the calendar so the plan respects reality:
is tools call google_google_calendar_atlassian_calendar_get_events \
--cloud-id "$ATLASSIAN_CLOUD_ID" \
--args '{"timeMin":"<today>T00:00:00Z","timeMax":"<today>T23:59:59Z","timeZone":"<user-tz>"}'
Meetings determine how much focus time exists. A plan that ignores a four-hour meeting block is fiction.
is tools call spinnaker_spinnaker_spinnaker_get_deployments \
--cloud-id "$ATLASSIAN_CLOUD_ID" --args '{"serviceName":"<service>"}'
Response nests environment, then region, then cluster, with stable.timestamp,
stable.createdBy and inProgress.
Three outcomes, and they must not be conflated:
stable.timestamp materially older than staging with nothing
inProgress. An unpromoted change, not a stuck pipeline. Report the gap in hours.inProgress is non-empty. A long-running or repeatedly failing stage
is a priority-one candidate.SERVICE component this is a monitoring gap worth surfacing.
Not healthy, not an outage.is tools call compass_compass_atlassian_component_get_package_dependencies \
--cloud-id "$ATLASSIAN_CLOUD_ID" --args '{"componentId":"<full-component-ari>"}'
is tools call migrations_find_migration \
--cloud-id "$ATLASSIAN_CLOUD_ID" --args '{"active":true,"pageSize":20}'
Migrations return status, statusReason, migrationSchedule and the sharding
context. Only report one when it touches a confirmed service or its dependencies.
twg jsm alert query --query 'status = open AND (message: *<service-a>* OR message: *<service-b>*)' \
--limit 30 --site hello -o json --agent-fields @evidence
Full Opsgenie search syntax, current state, responders included. Rows arrive under
data.values. Other useful forms: teams = "<team>", priority = P1, and
--sort createdAt|lastOccurredAt|priority --order asc|desc.
Compute alert age from createdAt. A production alert open for weeks is usually the
single most important item in the brief, and it will not stand out by priority alone —
a P2 open 20 days matters more than a P2 opened this morning.
Separate live signal from stale noise. Long-open non-production checks are a housekeeping item, not a top-five priority, but say how many there are: they mask genuine failures in any list of open alerts.
Optionally enrich an alert with jsm_..._operations_get_snr_insights using its
tinyId, type: alert and target_id_cloudId. It returns a signal-versus-noise
prediction, but frequently UNKNOWN — treat a verdict as a bonus and never let
UNKNOWN suppress an item.
Related: twg jsm incident query, twg jsm pir query, twg jsm alert get <id>.
Use twg for what is open now, and the warehouse for trends, counts and history.
is tools call reliability_insights_execute_socrates_query --cloud-id "$ATLASSIAN_CLOUD_ID" \
--args '{"query":"SELECT alert_id, message, priority, status, integration_name, created_utc FROM production.sre_incident.opsgenie_alerts WHERE day_of_created >= DATE_SUB(CURRENT_DATE(), 14) AND lower(message) LIKE '"'"'%<service>%'"'"' ORDER BY created_utc DESC LIMIT 20"}'
Always constrain on day_of_created — the table is partitioned on it and unbounded
scans time out. There is no service column, so match against message.
integration_name reveals the alert source, distinguishing a SignalFx detector from a
CloudWatch alarm.
# live HOT incidents - note the different catalogue path
is tools call reliability_insights_execute_socrates_query --cloud-id "$ATLASSIAN_CLOUD_ID" \
--args '{"query":"SELECT issuekey, summary, severity, status, start_utc FROM sre_incident_source.incident_landing ORDER BY batch_id DESC LIMIT 20"}'
# feature gate changes in the last 7 days
is tools call reliability_insights_execute_socrates_query --cloud-id "$ATLASSIAN_CLOUD_ID" \
--args '{"query":"SELECT changeId, eventTime, event, kind FROM production.experimentation_switcheroo.change_logs_prod WHERE eventTime >= DATEADD(day, -7, CURRENT_DATE()) ORDER BY eventTime DESC LIMIT 20"}'
Incidents use severity, not priority. The SQL dialect differs between tables — the
alert table filters day_of_created with DATE_SUB, the gate table filters eventTime
with DATEADD. Fetch canonical SQL per table with action: queries rather than reusing
a pattern from another table.
Filter out synthetic entries. incident_landing carries Pollinator check records and
rows marked [Do not touch] alongside real incidents.
A feature gate flipped shortly before a behaviour change is often the explanation, and it is cheap to check.
Read references/connector-auth.md and run its connector preflight before collection.
Do not assume that a token or MCP server available on the user's laptop is available in
RovoClaw Cloud.
If scope.json contains operationalRelay.url, read that Confluence live document
first. If the field is absent, search permitted Confluence content once for the exact
title Engineering Brief — Operational Signal Relay; attach it only when exactly one
creator-private page owned by the invoking user is found. The page must declare
Generated (UTC) and Valid until (UTC).
checked row satisfies direct coverage for that source and is labelled
checked via private operational relay, not checked directly by RovoClaw.The relay is the supported bridge when RovoClaw Cloud lacks a direct Splunk or
SignalFx tool. Its collector keeps Splunk SLAuth and the SignalFx token in the user's
local Keychain and publishes derived signals only. Setup and failure handling are in
references/local-operational-relay.md.
Start with the native JSM Ops alert routes. They are available to RovoClaw through TWG and keep source ACLs intact:
# SignalFx detector alerts: SLO burn, latency and success-rate breaches
twg jsm alert query --query 'source = SignalFx' --limit 50 \
--sort lastOccurredAt --order desc --site hello -o json
# Alerts created from Splunk searches
twg jsm alert query --query 'source = Splunk' --limit 50 \
--sort lastOccurredAt --order desc --site hello -o json
Match the returned message, tags and responder team against the confirmed services. Group repeated messages and keep the latest occurrence, priority, state and alert link. This is alert-derived coverage: it can identify a detector firing or a Splunk alert, but it does not provide raw logs or the current metric value.
Use direct Splunk or SignalFx queries only when RovoClaw tool discovery shows a
registered tool for the current principal. Read its schema, run one bounded aggregate
query and never retain raw events. The checked Splunk tool requires service, not
query; the checked SignalFlow tool requires programText, not program. Recover a
missing Splunk cache once through the SLAuth/MFA path in connector-auth.md. Treat a
SignalFx HTTP 401 as an expired-token action, not a platform fault. If a registered tool
still rejects a complete schema-valid request, report failed with the actual error. If
no registered tool exists, report not registered. In RovoClaw Cloud, do not invoke a
laptop process and do not keep retrying a denied or repeatedly failing route.
The alert path was checked on 2 September 2026: source = SignalFx returned current
SignalFx alerts and source = Splunk returned Splunk-originated alerts. This proves
alert coverage only; it does not prove direct telemetry access.
c360_..._query_customers, c360_..._query_licenses, zendesk_*, JSM tickets,
support_insights_*.
A customer-impact claim needs an explicit support or escalation artifact, or corroboration from two independent sources. One unhappy Slack message is not enough.
is tools call notifications --cloud-id "$ATLASSIAN_CLOUD_ID" --arg category=direct --arg first=30
Check Slack connection state first:
twg rovo list-apps -o json
When Slack is ready, use delegated Rovo search with an operational query built from
the confirmed service name and risk terms:
twg rovo search "<service> DLQ latency workflow failed production" \
--app slack --updated-since 7d --limit 50 -o json
twg rovo search is the delegated Slack route. Run it even when is tools does not
list a Slack message-search MCP tool; absence from the MCP catalogue does not mean the
connected Rovo search source is unavailable. If the CLI route itself is absent or
fails, report that runtime mismatch separately from Slack connection state.
Rovo search cannot enforce a channel ID in the request, so enforce the signal-pack
allowlist on every returned Slack URL before using it. The /archives/<channel-id>/
segment must match an allowlisted channel. Discard every other result, including DMs
and group DMs. Keep only the link, timestamp and a one-line derived signal; do not retain
the raw message body.
This route was checked on 2 September 2026 and returned ACL-respecting Slack message links for the current user.
Normalize every observation to: source, service, signal type, timestamps, severity, confidence, evidence URL, fingerprint. Deduplicate by service plus type plus fingerprint.
Rank on impact, urgency, service relevance, confidence, recency, recurrence.
These were learned expensively. Do not relax them.
not registered means the principal has no route;
failed means a registered route rejected a schema-valid probe; runtime unavailable
means discovery could not execute. Never report any of these as healthy.The brief answers one question: what does this engineer need to do today, and in what order. Open with a short narrative, then the actions. Do not make the reader assemble the story from alerts, tables, and repeated source rows.
Group corroborating observations by service and concern before rendering. For example, a Splunk DLQ event count and a SignalFx oldest-message metric are two pieces of evidence for one DLQ concern, not two competing first actions. Keep both evidence links and do not merge unrelated queues or workflows merely because they share a signal type.
Open with:
Use these supporting buckets after the action plan. Skip an empty bucket and collapse supporting detail in dashboards so the first screen remains readable.
1. Start here. One to three items. What breaks, blocks someone else, or has a deadline today. A production alert belongs here. So does a PR that has been waiting on the engineer's review for three days, because someone else is stalled behind it.
2. Your sprint. Assigned work with status, ordered by how close it is to finishing. Lead with anything in review or in progress, then spec work. State the shape of the sprint in one line, for example "18 of 20 still in spec on day nine" — that framing is more useful than twenty ticket titles.
3. Waiting on you. Review requests, comments needing a reply, approvals. These are cheap to clear and expensive to leave, because each one has a person behind it.
4. Your services. Deploy drift, alerts, ownership gaps, migrations. This is the infrastructure layer, and it sits below the work layer unless something is on fire.
5. Plan for the day. Two to four concrete blocks, fitted around the calendar. Name the meetings that constrain it. This is the part an engineer actually acts on, and it is the section most briefs omit.
Then the coverage table.
Each item still carries an owner, evidence link, timestamp, confidence and a next step. Routine commits never appear. Cap the visible total at ten across all buckets.
A finding without a fix is a complaint. Every priority must end with something a human can act on.
Split fixes by who owns them, and say which is which:
owner custom field, or the on-call schedule. Never say "the team should"
without naming who.Ground the fix in what the evidence supports. Deploy drift with nothing in flight means
"promote or confirm the hold", not "investigate the pipeline". Missing telemetry means
"raise a platform ticket", not "check the dashboard". A missing Compass field means
"add platform: micros to the component", which is a two-minute change, not an
investigation.
Prefer the smallest fix that resolves the finding. If a one-line config change and a migration would both work, propose the config change and note the migration as the durable option.
Do not execute the fix. Draft messages, tickets and PRs behind an explicit confirmation step. The brief informs and prepares; the human decides.
Same evidence, different framing. See references/personas.md.
| Persona | Leads with |
|---|---|
| Engineer / on-call | latency, errors, SLO burn, DLQ age, stuck workflows, failed deploys, red CI, migration risk, runbooks |
| Engineering manager | aggregated service and delivery risk, recurring failures, ownership gaps, cross-team blockers, 30/90-day trends |
| PM | customer escalations, adoption, roadmap risk, deadlines, migration commitments, dependencies |
Manager view is aggregate only: no private messages, no individual activity scoring, no per-person attribution.
For rolling this out across a team — install steps, signal-pack ownership, rollout
order and common failure modes — see references/team-adoption.md, and
references/install-for-teammates.md for RovoClaw workspace installation and what a
teammate gets on day one.
Chat: the five buckets in order, then a one-line coverage summary.
Dashboard: load /opt/atlassian/skills/design-kit/SKILL.md and author
memory/engineering-brief/index.html.
The daily-briefing template is a singleton reserved for memory/daily-briefing, so
use --template custom. On refresh, update in place with --replace-content against
the published folder, because --publish refuses to overwrite an existing dashboard.
After a skill update, rebuild and replace the dashboard; never reuse an older page or
coverage rows. Validate before and after. Only design-kit classes are permitted.
The dashboard runtime must visibly show brief-engineering 1.0.7 and the preflight
timestamp. Render its Coverage section only from the current run's deterministic
connector-preflight output; do not merge, cache, or retain rows from an earlier run.
Make the first screen calm. Use one column, generous spacing, plain Atlassian-style type and colour, and no decorative hero image. The reader should see the story and three actions without scrolling through connector detail. Render:
| Section | Contains |
|---|---|
| Today in one minute | One human summary of the main theme and secondary concerns |
| Action plan | Up to three numbered, evidence-backed next actions |
| What needs attention | Up to five grouped concerns; evidence is collapsed |
| Supporting context | Collapsed sprint, waiting-on-you, service, and day-plan sections |
| Source coverage | Collapsed current-run preflight and per-source status |
No stat grid, repeated headline, duplicate action, or wall of connector text. Counts belong in the lead paragraph only when they add meaning. A partial or unavailable source stays visible in the collapsed coverage summary and is never presented as healthy.
Put suppressed context in a collapsed accordion at the bottom. Write task and update state to the shared core memory files, never to a dashboard-local JSON. Close a task when a run resolves it, and record what resolved it.
Always close with per-source status. This is what makes the brief trustworthy.
spinnaker checked 5 services queried, 3 returned state
compass checked 6 components, ownership resolved
compass-oncall checked empty for all - ownership gap
compass-deps checked no dependency edges recorded
migrations checked active TPS tasks, none touching scope
operational-relay checked fresh creator-private snapshot; expires at <timestamp>
signalfx-values checked via private operational relay
atlassian-work checked 13 issues, 150 dev events
notifications checked direct notifications retrieved
splunk-alerts checked Splunk-originated JSM Ops alerts
direct-splunk checked via private operational relay
# A discovered direct route that rejects a complete schema-valid aggregate is distinct:
# direct-splunk failed action=repair the registered Ops Sherpa RovoClaw runtime
# signalfx-values failed action=repair the registered SignalFx RovoClaw runtime
slack checked delegated search, allowlist enforced
apollo-opensearch unavailable server-side failure
snr + change-win blocked need an alert id from the failing alert search
forge-usage unavailable no tool exists
cron add: weekday 08:30 in the user's timezone, isolated agentTurn,
timeoutSeconds 1800, message "Run the brief-engineering skill"
Verified in production: a full run takes roughly 14 minutes when it attempts every connector. Budget at least 1800 seconds. A 900-second budget completed with only 64 seconds to spare, which is not enough margin for a slow morning.
Two things keep the runtime down:
Delivery is managed by RovoClaw. Setting delivery.mode on the job reverts to none;
the run summary is recorded in the Activity feed automatically. Do not write to
memory/activity-feed/** from the run.
Check a run afterwards with cron get: lastRunStatus, lastDurationMs and
consecutiveErrors tell you whether it completed and how close to the budget it came.
While a run is in flight the job shows runningAtMs and no run history — that is
normal, not a hang.
jsm_..._operations_search_services: fails on every documented input shape. Use
compass_..._component_search for ownership instead.npx @atlassian/skills add ... needs public egress to
statlas.prod.atl-paas.net and npm. Where that is unavailable, call the underlying
is tools directly — references/signal-catalog.md lists them.not registered.