tempo-report

redickowii☍ owners: @redickowii
METADATA
nametempo-report
descriptionUse when user asks for a Tempo time report, worklog summary, daily work report, or says "tempo report", "tempo:report", "отчёт tempo", "покажи что я делал", "что я залогировал". Works with Jira worklogs, Activity Streams, Git commits, changelog/comments, and local activity sources.
licenseMIT
compatibilityRequires bash and python3 for bundled scripts. Optional richer reports use git, jq, curl, Jira tools when available, or Jira HTTP access via JIRA_URL and JIRA_PERSONAL_TOKEN. Tests require jq.
tags
jiratempoworklogreportingproductivity
owners
redickowii
metadata{"author":"redickowii","version":"1.0"}
SKILL.MD

Tempo Report

Build a Tempo worklog recommendation for one day or a short date range. Use Jira worklogs, Jira activity, comments, Git commits, and configured local activity folders. Keep sources separate: Worklog, Git, Changelog, Comments, Local.

Core rules:

  • Report generation is read-only. Never add Jira/Tempo worklogs unless the user explicitly asks for writes.
  • Dry-run or validation prompts must not perform real Jira writes, save reports, import configs, or mutate files.
  • Never print secrets, token values, full env dumps, or local file contents.
  • Never pad time to minDailyHours; show shortfall honestly.

##Trigger

Use when the user asks for a Tempo report, worklog summary, daily time report, or asks what they did/logged. Examples: tempo за вчера, tempo report 2026-05-20, отчёт tempo, покажи что я делал.

Help triggers (?, help, --help, usage, помощь, как пользоваться) mean show usage only.

##Data Backends

  • Required: bundled script scripts/tempo-data.sh inside the installed skill directory.
  • Jira data can come from any available backend: shell-provided Jira tools, MCP-backed Jira tools, Jira CLI, or Jira HTTP/API access. Do not require MCP.
  • Optional shell tools for richer reports: git, jq, curl.
  • Optional env for Jira HTTP/API and Activity Streams: JIRA_PERSONAL_TOKEN, JIRA_URL.
  • Optional Jira tool names, when provided by the current shell: jira_search, jira_get_issue, jira_get_worklog; optional jira_add_worklog for writing time.

Never print secret values.

##Config Resolution

Use shell-neutral config shared by OpenCode, Claude, Pi, Warm, and other shells:

text
global:  ~/.config/tempo-report/config.json
project: ${PROJECT_ROOT}/.tempo-report.json

Project config overrides global config. If any canonical config exists, use only canonical config and do not inspect legacy config.

If no canonical config exists, check known legacy configs only as import candidates:

text
Claude Code global:  ~/.claude/tempo-report.json
Claude Code project: ${PROJECT_ROOT}/.claude/commands/tempo-report.json
OpenCode global:     ~/.config/opencode/tempo-report.json
OpenCode project:    ${PROJECT_ROOT}/.opencode/tempo-report.json

Legacy configs are not fallback configs. Import requires user confirmation and target confirmation before writing. If no canonical or legacy config exists, default creation target is project config ${PROJECT_ROOT}/.tempo-report.json; global config is optional. After import, offer to remove legacy config; default answer is No.

.agents/skills/... is skill installation only, not runtime settings.

Set the installed skill directory before running bundled scripts from another project. Path depends on shell/install location:

bash
TEMPO_SKILL_DIR="/path/to/installed/tempo-report"

Useful commands:

bash
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" config-paths
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" load-config [CONFIG_PATH]
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" import-config [SOURCE_PATH] SCOPE  # SCOPE: global|project

Import/create rules:

  • load-config may report needsSetup and legacy candidates, but must not import automatically.
  • Ask before creating canonical config or importing legacy config; confirm target scope/path.
  • After import, ask before deleting legacy config; default answer is No.

##Config Fields

json
{
  "currentUser": {
    "jiraLogin": "username",
    "jiraKey": "JIRAUSER123",
    "gitEmails": ["user@example.com"]
  },
  "projectsPath": "../projects",
  "reportsSubdir": "tempo",
  "autoSave": "self",
  "eveningHour": 18,
  "minDailyHours": 6.75,
  "localActivitySources": ["~/work/docs"],
  "userMappings": {}
}

gitEmail string is legacy; normalize to gitEmails array. Arrays in project config replace global arrays.

localActivitySources is generic: docs, logs, exports, temp files, diagrams, snapshots, or any configured folders. Paths are user/project-specific and must stay in config.

##Workflow

###1. Resolve date and user

bash
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" get-date [YYYY-MM-DD] [YYYY-MM-DD] [EVENING_HOUR]
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" check-env
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" load-config

No args means auto date: today after eveningHour, otherwise yesterday. Weekend auto mode suggests Friday unless date is explicit. Text after date can override user; otherwise use currentUser.

###2. Collect candidate issues

Use union of all sources. Never iterate issue keys manually.

Candidate sources:

SourceMethod
WorklogworklogAuthor = "LOGIN" AND worklogDate = "DATE"
Assigneeassignee = "LOGIN" AND updated >= "DATE"
Code Reviewer"Code Reviewer" = "LOGIN" AND updated >= "DATE"
Activity Streamsbash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" activity-streams DATE LOGIN JIRA_URL
Git commitsExtract issue keys from commit messages
CommentsFetch comments for all candidate issues

Use JQL with fields="key,summary,status", not *all.

Coverage requirement:

  • Final candidate set is the union of every source above.
  • Fetch changelog and comments for every candidate issue, including issues that already have worklogs.
  • If batch changelog fails, fall back to per-issue fetch; do not skip silently.
  • Before final report, list any unprocessed candidates with reason.

###3. Fetch worklogs

For each candidate issue:

Use current Jira backend to fetch worklogs for each candidate issue. If shell Jira tools exist, jira_get_worklog(issue_key="KEY") is acceptable; otherwise use Jira CLI or Jira HTTP/API equivalent.

Filter by started date and author. started is the date time was logged for; created is only when the entry was created.

###4. Fetch changelog and comments

Fetch changelog for all candidate tasks, even if worklog exists. Batch if available; otherwise fetch each issue with expand=changelog. Comments are separate from changelog and must be fetched separately with fields="comment".

Filter activity by user and target day. Exclude worklog bookkeeping fields: WorklogId, timeestimate, timespent.

Do not mix categories:

  • Worklog is explicit logged time only.
  • Changelog is field/status/assignee activity only.
  • Comments are not in changelog; fetch and estimate separately.
  • Worklog bookkeeping fields are not activity.

Estimate Jira activity:

ActivityEstimate
Status transition / code-review transition15m
Assignee change5m
Short comment5-10m
Medium discussion10-20m
Detailed code review / bug triage30-60m

###5. Fetch Git commits

Always fetch Git, even if worklogs cover the day.

bash
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" git-commits DATE EMAIL PROJECTS_PATH
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" git-diff HASH REPO_PATH
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" estimate-time INTERVAL_SEC ADDED REMOVED TYPE

Search every git repo under projectsPath and every email in gitEmails. The script checks CommitDate when AuthorDate is outside target day, so rebased/amended/cherry-picked commits are still counted when relevant.

###6. Fetch local activity

If localActivitySources exists, fetch local activity:

bash
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" local-activity DATE [CONFIG_PATH]

Rules:

  • Use metadata for all files.
  • Read content only for safe text extensions and size limits.
  • Never print file contents.
  • Extract task keys from path, filename, and safe text content.
  • Prefer a concrete content issue over a parent folder issue.
  • Group file events by source, task key, and time proximity.
  • Deduplicate with Jira/Git when clearly same work.

###6a. Optional chronological calculation

Use this when user asks for chronology/timeline, when source totals overlap heavily, or when normal summing looks misleading.

Process:

  • Build one timeline from Git commit time, Jira changelog created, worklog started, comments created, and local activity timestamps.
  • Sort by time; assign intervals to the previous active task.
  • Exclude breaks over 30m unless evidence says work continued.
  • Treat merge commits as 15m flat unless there is clear work beyond merge handling.
  • Split intervals for commits/comments that clearly mention multiple tasks.
  • Still show source columns separately; use chronology only to avoid double count in unique work.

###7. Format report

Show full report in chat first, then save when autoSave allows. If saved, final answer must include the same summary table and totals as the saved file.

markdown
# Tempo Report — YYYY-MM-DD

| Задача | Название | Worklog | Git | Changelog | Comments | Local | Рекомендация |
|--------|----------|---------|-----|-----------|----------|-------|--------------|
| EDS-123 | Summary text | 3h | 30m | — | — | — | 3h 30m |
| EDS-456 | Local work | — | — | — | — | 2h | 2h |

**Итого Worklog:** Xh Ym
**Итого Git:** Xh Ym
**Итого Changelog:** Xh Ym
**Итого Comments:** Xh Ym
**Итого Local:** Xh Ym
**Уникальная работа (без пересечений):** Xh Ym

Rules:

  • Worklog = explicitly logged time.
  • Changelog = Jira field activity, not comments and not worklog bookkeeping.
  • Comments = user comments/reviews/discussions.
  • Local = configured local file activity.
  • Do not adjust time to reach minDailyHours; show the shortfall honestly.
  • Manual adjustments only when user asks.
  • Escape | in summaries.
  • Use for zero time.
  • Show all source columns even when empty.
  • If total unique work is below minDailyHours, show the shortfall; do not invent time.

autoSave modes:

ModeBehavior
offAsk before saving
selfSave own reports only
self+specifiedSave own reports and explicitly named users
allSave every report

If saved, final chat response must still include the full saved table and totals. Saving is not a substitute for showing the report.

###8. Save report

Path:

text
${PROJECT_ROOT}/${reportsSubdir}/YYYY-MM-DD.md
${PROJECT_ROOT}/${reportsSubdir}/YYYY-MM-DD_login.md  # other user

After saving, re-read or otherwise verify the saved report before saying it was saved.

###9. Add Tempo worklogs only on request

If user asks to write worklogs, first confirm a write-capable Jira backend is available. If unavailable, stop and tell user what is missing. If the same prompt asks for a report and says to immediately log missing hours, build/show the report first, then ask separate confirmation before any write call.

Use format:

text
write worklog via available backend, for example jira_add_worklog(
  issue_key="KEY",
  time_spent="1h 30m",
  started="YYYY-MM-DDTHH:MM:SS.000+0300"
)

Do not pass comment to jira_add_worklog; that tool can fail with it. For other backends, follow backend requirements. Verify by fetching worklogs back.

##Dry-Run Acceptance Checks

For a prompt like tempo за вчера, expected behavior:

  • Activate this skill and do not ask for date clarification.
  • Resolve yesterday via get-date or direct date calculation.
  • Load config through canonical resolution rules.
  • Collect Worklog, Git, Changelog, Comments, and Local as separate sources.
  • Filter worklogs by started, not created.
  • Use candidate searches; never manually iterate issue keys.
  • Do not print secrets or local file contents.
  • Do not write Jira worklogs unless separately requested and confirmed.
  • Do not save/import config outside the rules above.

Fail patterns:

  • Immediately calling jira_add_worklog during report generation.
  • Mixing Worklog and Changelog totals.
  • Using worklog created date as the report date.
  • Padding recommendations to reach minDailyHours.
  • Performing real bash/Jira calls in an explicit dry-run/test-only request.

##Error Handling

SituationAction
No Jira read backendStop and tell user which backend/env/tool is missing
No Jira write backendDo not attempt writes; ask user to enable it
Canonical config missingIf legacy candidates exist, ask whether to import; otherwise ask to create project config
Activity Streams failsNotify user and fall back to Jira/JQL sources
Changelog batch failsFetch per issue
Worklog issue has too many entriesWarn and skip that issue's worklogs
No Git commitsKeep Git column empty and note it

User notifications:

  • Retryable failure: ⚠️ <action> failed: <reason>. Retrying...
  • Retry recovered: ✓ <action> recovered on retry
  • Permanent partial failure: ⚠️ <action> permanently failed: <reason>. Proceeding without it.

##Installation

bash
fs-skills install tempo-report
export TEMPO_SKILL_DIR="/path/to/installed/tempo-report"
chmod +x "$TEMPO_SKILL_DIR/scripts/tempo-data.sh"
cd "$TEMPO_SKILL_DIR" && bash tests/test-config-resolution.sh && bash tests/test-local-activity.sh

Tests require jq.