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.

Runtime root rules:

  • PROJECT_ROOT means the real report project root: the user's current working copy or an explicitly requested project path.
  • If the current working directory contains .tempo-report.json, project-local mode is active: MUST use PROJECT_ROOT=./ and tool workdir set to that directory.
  • In project-local mode, using an absolute PROJECT_ROOT for the same directory is a fail pattern; absolute roots are only for running from outside the report project or for global/shared settings.
  • Before any config/report command, choose PROJECT_ROOT explicitly and keep it fixed for the whole report.
  • Run bundled scripts with tool workdir set to the current report project (project-local ./) or set TEMPO_PROJECT_ROOT to PROJECT_ROOT before invoking the script.
  • Do not use $HOME, /tmp/opencode, /tmp, the skill install directory, or another temporary folder as runtime workdir.
  • If root is ambiguous, ask the user for the project path before running config/report commands.
  • If a command returns invalid report project root, STOP and ask for PROJECT_ROOT; do not glob, search, or inspect $HOME to discover configs.

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"
PROJECT_ROOT="./"  # project-local when cwd contains .tempo-report.json

Useful commands:

bash
# From the report project directory, use PROJECT_ROOT=./.
# From outside the project, use an absolute PROJECT_ROOT and tool workdir set to that path.
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, root, and user

Preflight:

  1. Resolve the date with any safe workdir.
  2. If the current working directory contains .tempo-report.json, set project-local PROJECT_ROOT=./.
  3. Otherwise resolve PROJECT_ROOT from the user's explicit request or known current workspace.
  4. If PROJECT_ROOT is unclear, ask; do not search $HOME.
  5. Run every config/report command with tool workdir set to the report project or TEMPO_PROJECT_ROOT=PROJECT_ROOT.
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
TEMPO_PROJECT_ROOT="$PROJECT_ROOT" 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.
  • Candidate discovery is not attribution: do not count time unless the task is definitely identified and has direct evidence for the target day.
  • Keep weak candidates, zero-evidence candidates, and unmapped activity out of the main recommendation table.

###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.
  • Count local-only time only when the Jira task key appears in the path segment or filename of the active file/directory for that event.
  • Do not count local time from content-only mentions, metadata-only mentions, inferred context, or repeated edits without a Jira key in path/filename; report them in the warning/appendix, not totals.
  • If local activity clearly belongs to a project/folder but no exact Jira task is determined, keep it unmapped and warn the user that it may need mapping to an existing or new task.
  • 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

## Warning: ambiguous or unmapped activity (not counted)

- `repo/path` or commit summary without Jira key — Xm, not counted; ask user whether to map to an existing task or create a new one.
- Weak local mention `EDS-0000` found only in file content — not counted without stronger evidence.

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.
  • Count time in the main report only for definitely identified Jira tasks with direct evidence for the target day.
  • Do not count weak or ambiguous evidence in recommendations: content-only local key mentions, metadata-only local mentions, local-only activity without Jira key in path/filename, assignee/reviewer candidates without user activity, Activity Streams candidates without user changelog/comment/worklog/git/local evidence, and git commits without a Jira key.
  • Put ambiguous/unmapped activity after all totals in a separate warning/appendix section. Use it only to help the user understand folders/projects/possible future tasks; do not include it in totals or recommendations.
  • Do not create NO-ISSUE rows in the main recommendation table. Unmapped git belongs in the warning/appendix section.
  • Do not include zero-time Jira candidates in the main table; list them only as unprocessed/zero-evidence candidates if useful.
  • 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 for counted tasks.
  • If total unique work is below minDailyHours, show the shortfall; do not invent time.

###7a. Main table validation contract

Before showing or saving a report, validate the main recommendation table.

The main table MUST NOT contain:

  • NO-ISSUE rows.
  • LOCAL-ACTIVITY rows.
  • Rows with zero recommendation (, 0m, or all source columns empty).
  • Local-only rows unless the evidence explicitly says the Jira key appeared in the active file path segment or filename.
  • Assignee/reviewer/activity-stream candidates without direct same-day user evidence.
  • Git-only rows whose commit subject/body/path has no Jira key.

If any row violates this contract:

  1. Remove it from the main table.
  2. Move it to Warning: ambiguous or unmapped activity (not counted) with the reason it was not counted.
  3. Recalculate totals without that row.
  4. Only then show/save the report.

A report that violates this contract is invalid and must not be saved as the final report.

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.
  • Resolve PROJECT_ROOT before config/report commands; use ./ when the current project contains .tempo-report.json; if unclear, ask instead of searching $HOME.
  • Load config through canonical resolution rules with tool workdir set to the report project or TEMPO_PROJECT_ROOT=PROJECT_ROOT.
  • Collect Worklog, Git, Changelog, Comments, and Local as separate sources.
  • Filter worklogs by started, not created.
  • Use candidate searches; never manually iterate issue keys.
  • Include only definitely identified tasks with non-zero direct evidence in the main counted table.
  • Validate the main table contract before showing/saving: no NO-ISSUE, LOCAL-ACTIVITY, zero-time rows, or unqualified local-only rows.
  • Put weak/unmapped/zero-evidence activity after totals as warnings/appendix only.
  • 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.
  • Counting NO-ISSUE, LOCAL-ACTIVITY, weak local mentions, local-only activity without Jira key in path/filename, or zero-evidence candidates in the main recommendation table.
  • Saving a report before the main table validation contract passes.
  • Using an absolute PROJECT_ROOT when current cwd already contains project-local .tempo-report.json.
  • Performing real bash/Jira calls in an explicit dry-run/test-only request.

##Error Handling

SituationAction
Invalid report project rootStop and ask for PROJECT_ROOT; do not search or glob $HOME
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.