omp-worklog 0.16.1 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7acbe94c0d9ab3889a488877a4d75a94b0adfc9172b67f81620f218b854ba384
4
- data.tar.gz: dc6f213011f9e8042e1330c6d6ed408474b775f852437cb617001e463fd22bed
3
+ metadata.gz: 2378eac4f1eb8bca8441db76d31ec0b2025fbb2e129a04c6c1b2787da9c399cc
4
+ data.tar.gz: e5488122f526ea17fbd2c12d9987dc21b374b5cb570ce8aa64224aa914a23e6c
5
5
  SHA512:
6
- metadata.gz: fc0d66c2d93b6773fa6257537498a9a44870cd539a6959a7713e0e8ebc88839a41a1e905cb4bd9c3267474fa6a02bae2472e73563885dec00dad5f48f08250de
7
- data.tar.gz: 99a9f450cae0c23de7e58af186c05dfc2ce85ae73826b86842cf766832642b09faf3908abecb0e0ac76c0cf9a956fddd636211816208fe73694e0e31db90caf7
6
+ metadata.gz: 05f29b0ea9f0b21deaabf34b087531a2d7921cb84fae146f3eabbf63e7c0e8af7c237950e1ae689ee8ce2f200a28696ffc7141d5d3d8127ba0065bfc99fe7c80
7
+ data.tar.gz: 715ec5513e40a6c80a6ba41de4d3cb2386b1809cbe1e1dece61b9b7bb8feaca229d1a5c26cf5ecba262235a8815d31d3cbc1fa16d8f6bda6c674254d0e3fe976
data/README.md CHANGED
@@ -52,6 +52,14 @@ The `omp_worklog_record_time_off` OMP tool accepts the same name pair or ID pair
52
52
 
53
53
  The `work-entry` command checks for existing or locked entries for its project, task, and date before creating a new duration entry. Use `--dry-run` to complete that preflight without a write.
54
54
 
55
+ ### Live thread time
56
+
57
+ With OMP Project Time 9.6.0 or newer installed, Worklog shows one normal-contrast status line for the current top-level thread and project. **Dev** is observed prompt-active time; **Agent** is observed agent-run elapsed time. Durations use `H:MM:SS`; long project labels are shortened so both counters remain readable at ordinary terminal widths. A paused developer window does not stop an ongoing agent run. These are independent evidence counters, not a combined total, desk-time certification, cost estimate, or billing approval.
58
+
59
+ Worklog receives versioned live snapshots from Project Time through OMP's extension event bus. It does not run a second activity clock or alter the evidence ledger. Project Time hides its standalone status while Worklog owns presentation, and keeps its standalone display when Worklog is absent. Missing or incompatible live evidence shows unavailable counters rather than fabricated zero hours.
60
+
61
+ The scope is this thread's current project, not all threads or today's entire project total. Use `/worklog stats today --project PROJECT` for daily evidence and `/worklog review` for reviewed records. Restart OMP after installing both releases; an already-running process keeps its startup-loaded extensions.
62
+
55
63
  ### Project Time timesheets
56
64
 
57
65
  `/worklog timesheet DATE` reads local `human_active` Project Time evidence and produces one review-only draft for every local project active on that day. It does not call Harvest or require Harvest credentials.
@@ -81,9 +89,9 @@ Type `/worklog ` to discover review, timesheet, stats, plan, and submit. Date al
81
89
 
82
90
  ### Daily Human and AI Reports and Reviewed Batches
83
91
 
84
- At the end of a workday, run `/worklog review`. It opens today's worklog inside OMP: edit each project's duration, destination, and factual note, then choose **Mark reviewed** or **Exclude entry**. When all retained entries are ready, choose **Submit to Harvest** once. No JSON editing or path copying is required. Use `/worklog review yesterday` for another day.
92
+ At the end of a workday, run `/worklog review`. It opens today's worklog inside OMP: edit each project's duration, destination, and factual note, then choose **Mark reviewed** or **Exclude entry**. A duration above the automatic candidate also requires **Edit adjustment reason**. When all retained entries are ready, choose **Submit to Harvest** and confirm the displayed snapshot. No JSON editing or path copying is required. Use `/worklog review yesterday` for another day.
85
93
 
86
- **Save and close** preserves your private draft for the next run. **Refresh evidence** rebuilds the snapshot after confirmation and retains the prior draft privately. Review does not submit anything until you explicitly choose Submit.
94
+ **Save and close** preserves your private draft, including correction reasons, for the next run. **Refresh evidence** rebuilds the snapshot after confirmation, clears corrections and review state, and retains the prior draft privately. Review does not submit anything until you approve the final confirmation.
87
95
 
88
96
  ```text
89
97
  /worklog stats 2026-10-05 2026-10-18
@@ -138,6 +146,18 @@ Version `0.14.0` is a clean identity cutover. Uninstall the retired `harvest-wor
138
146
 
139
147
  Version `0.14.3` renames the OMP slash command from `/omp-worklog` to `/worklog`; the `omp-worklog` package identity and CLI executable are unchanged.
140
148
 
149
+ ## Changes in 0.18.0
150
+
151
+ - Show normal-contrast current-thread/project developer and agent time in one Worklog status line.
152
+ - Consume Project Time's live observation contract without duplicating clocks or mixing the two evidence sources.
153
+ - Clear stale counters across session changes and show unavailable evidence explicitly.
154
+
155
+ ## Changes in 0.17.0
156
+
157
+ - Allow explicitly reviewed duration increases with a required private adjustment reason, without changing the automatic candidate or source evidence.
158
+ - Preserve corrections across save/resume and show candidate, reviewed duration, and rationale in the final approval.
159
+ - Keep native review, saved-batch validation, and Ruby filing consistent while retaining duplicate and uncertain-outcome protections.
160
+
141
161
  ## Changes in 0.16.1
142
162
 
143
163
  - Keep the time-off tool's numeric schema compatible with Codex requests.
@@ -19,8 +19,10 @@ module OmpWorklog
19
19
  ENTRY_KEYS = %w[
20
20
  id spentDate localProject project task candidateMilliseconds milliseconds
21
21
  humanActiveMilliseconds agentTurnMilliseconds bridgedGapMilliseconds
22
- sourceEntryIds notes reviewed reviewReasons
22
+ sourceEntryIds notes reviewed reviewReasons adjustmentReason
23
23
  ].freeze
24
+ REQUIRED_ENTRY_KEYS = (ENTRY_KEYS - ["adjustmentReason"]).freeze
25
+ MAX_SAFE_INTEGER = 9_007_199_254_740_991
24
26
 
25
27
  class InputError < StandardError
26
28
  attr_reader :code
@@ -136,7 +138,7 @@ module OmpWorklog
136
138
  end
137
139
 
138
140
  def validate_entry!(entry, from, to, seen_ids)
139
- require_hash_with_keys!(entry, ENTRY_KEYS, "invalid_entry_schema")
141
+ require_entry_keys!(entry)
140
142
  spent_date = valid_date!(entry["spentDate"], "invalid_entry_date")
141
143
  raise InputError, "entry_date_out_of_range" unless spent_date.between?(from, to)
142
144
 
@@ -149,7 +151,13 @@ module OmpWorklog
149
151
 
150
152
  candidate = positive_integer!(entry["candidateMilliseconds"], "invalid_duration")
151
153
  milliseconds = positive_integer!(entry["milliseconds"], "invalid_duration")
152
- raise InputError, "duration_exceeds_candidate" if milliseconds > candidate
154
+ adjustment_reason = entry["adjustmentReason"]
155
+ if entry.key?("adjustmentReason") && !adjustment_reason.is_a?(String)
156
+ raise InputError, "invalid_entry_schema"
157
+ end
158
+ if milliseconds > candidate && (!adjustment_reason.is_a?(String) || adjustment_reason.strip.empty?)
159
+ raise InputError, "duration_increase_requires_reason"
160
+ end
153
161
 
154
162
  nonnegative_integer!(entry["humanActiveMilliseconds"], "invalid_entry_schema")
155
163
  nonnegative_integer!(entry["agentTurnMilliseconds"], "invalid_entry_schema")
@@ -173,6 +181,13 @@ module OmpWorklog
173
181
  }
174
182
  end
175
183
 
184
+ def require_entry_keys!(entry)
185
+ unless entry.is_a?(Hash) &&
186
+ (entry.keys.sort == REQUIRED_ENTRY_KEYS.sort || entry.keys.sort == ENTRY_KEYS.sort)
187
+ raise InputError, "invalid_entry_schema"
188
+ end
189
+ end
190
+
176
191
  def require_approval!(batch)
177
192
  raise InputError, "batch_not_approved" unless @dry_run || batch[:approved]
178
193
  end
@@ -188,7 +203,7 @@ module OmpWorklog
188
203
  end
189
204
 
190
205
  def positive_integer!(value, code)
191
- raise InputError, code unless value.is_a?(Integer) && value.positive?
206
+ raise InputError, code unless value.is_a?(Integer) && value.positive? && value <= MAX_SAFE_INTEGER
192
207
 
193
208
  value
194
209
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmpWorklog
4
- VERSION = "0.16.1"
4
+ VERSION = "0.18.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omp-worklog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.1
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marlen Brunner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-20 00:00:00.000000000 Z
11
+ date: 2026-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: marlens-harvest-api-v2