mps 0.5.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 +7 -0
- data/.github/workflows/main.yml +29 -0
- data/.gitignore +13 -0
- data/CLAUDE.md +102 -0
- data/GETTING_STARTED.md +447 -0
- data/Gemfile +6 -0
- data/IMPROVEMENTS.md +90 -0
- data/README.md +183 -0
- data/Rakefile +18 -0
- data/bin/console +38 -0
- data/bin/setup +8 -0
- data/exe/mps +5 -0
- data/lib/cli/mps.rb +442 -0
- data/lib/mps/config.rb +64 -0
- data/lib/mps/constants.rb +68 -0
- data/lib/mps/elements/element.rb +49 -0
- data/lib/mps/elements/elements.rb +6 -0
- data/lib/mps/elements/log.rb +32 -0
- data/lib/mps/elements/mps.rb +15 -0
- data/lib/mps/elements/note.rb +15 -0
- data/lib/mps/elements/reminder.rb +16 -0
- data/lib/mps/elements/task.rb +19 -0
- data/lib/mps/engines/engines.rb +1 -0
- data/lib/mps/engines/mps.rb +108 -0
- data/lib/mps/interpolators/interpolators.rb +1 -0
- data/lib/mps/interpolators/time.rb +11 -0
- data/lib/mps/mps.rb +32 -0
- data/lib/mps/store.rb +75 -0
- data/lib/mps/version.rb +5 -0
- data/lib/mps.rb +21 -0
- data/mps.gemspec +49 -0
- data/rust_rollout_spec.md +935 -0
- metadata +258 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7f0d20f2919cb1ee0ae46a3fe6eaef005af856eabd4650fc5e6e07477b5e7fb3
|
|
4
|
+
data.tar.gz: 259a623e9ee4b8edea593ab16a270b11015a55e3e22564359a424610f0510caa
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4653dca542034d736e5e61c69b2750c5ddb119c141876fac896b3f15e79d3d758f9e299a3ecf75fd17c52c5e7dbd8da9a562be228d760c6e4a7ba290359c83b0
|
|
7
|
+
data.tar.gz: 9cf8bf1273e814ed6708561c1f7cd5b82917e804b0e97e867d34c50bb2f35e762067f3df3493cb59eb4eea3ab0e5b1be9e02c38cbc7fffb43c9b9494c4790be3
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
- release/*
|
|
8
|
+
pull_request:
|
|
9
|
+
branches:
|
|
10
|
+
- master
|
|
11
|
+
- dev
|
|
12
|
+
- release/*
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v2
|
|
19
|
+
- name: Set up Ruby
|
|
20
|
+
uses: ruby/setup-ruby@v1
|
|
21
|
+
with:
|
|
22
|
+
ruby-version: 3.0.2
|
|
23
|
+
- name: Run the default task
|
|
24
|
+
run: |
|
|
25
|
+
gem update --system
|
|
26
|
+
gem install bundler -v 2.2.13
|
|
27
|
+
bundle add rake
|
|
28
|
+
bundle install
|
|
29
|
+
bundle exec rake
|
data/.gitignore
ADDED
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
MPS (MonoPsyches) is a Ruby gem — a plain-text personal productivity CLI. Users store tasks, notes, reminders, and logs in date-stamped `.mps` files (e.g. `20260226.1730000000.mps`) inside a configurable storage directory (`~/.mps/mps/` by default). Files are opened in Vim; git integration handles sync.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Install dependencies
|
|
13
|
+
bundle install
|
|
14
|
+
|
|
15
|
+
# Run all tests
|
|
16
|
+
bundle exec rake test:with_groups
|
|
17
|
+
|
|
18
|
+
# Run a single test file
|
|
19
|
+
bundle exec ruby -Itest -Ilib test/config_test.rb
|
|
20
|
+
|
|
21
|
+
# Run a single test by name
|
|
22
|
+
bundle exec ruby -Itest -Ilib test/config_test.rb -n test_name
|
|
23
|
+
|
|
24
|
+
# Build the gem
|
|
25
|
+
gem build mps.gemspec
|
|
26
|
+
|
|
27
|
+
# Run the CLI locally
|
|
28
|
+
bundle exec exe/mps
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# List parsed elements from today's (or a given date's) file
|
|
33
|
+
bundle exec exe/mps list [DATESIGN] [--type task|note|log|reminder]
|
|
34
|
+
|
|
35
|
+
# Append a single element without opening Vim
|
|
36
|
+
bundle exec exe/mps append TYPE BODY [--tags work,release] [--at 3pm]
|
|
37
|
+
|
|
38
|
+
# Auto stage, commit, pull, and push inside storage_dir
|
|
39
|
+
bundle exec exe/mps autogit
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Set `MPS_DEBUG=true` to enable verbose `require_relative` tracing via the custom `ir()` loader.
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
### Entry point
|
|
47
|
+
`exe/mps` calls `MPS::CLI::MPS.start(ARGV)` — a Thor-based CLI defined in `lib/cli/mps.rb`. All commands (`open`, `git`, `autogit`, `list`, `append`, `cmd`, `version`) live there and delegate to the library layer.
|
|
48
|
+
|
|
49
|
+
### Custom loader (`ir`)
|
|
50
|
+
`lib/mps/mps.rb` defines a global helper `ir(relative_path)` that wraps `require_relative` with caller-location resolution. All internal requires use `ir` instead of `require_relative`. This is intentional — don't replace it with standard requires.
|
|
51
|
+
|
|
52
|
+
### Load order (`lib/mps.rb`)
|
|
53
|
+
```
|
|
54
|
+
mps/version → mps/mps (defines ir + MPS module methods) →
|
|
55
|
+
mps/constants → mps/config → mps/interpolators → mps/elements → mps/engines → cli/mps
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Parsing pipeline (`lib/mps/engines/mps.rb`)
|
|
59
|
+
`Engines::MPS.parse_mps_file_to_elments_hash` reads an `.mps` file and uses `StringScanner` to tokenize it. It wraps the raw file contents in a synthetic `@mps[]{}` root element, then does a single-pass scan driven by two regexes from `Constants`: `AT_REGEXP_LA` (lookahead for `@element[args]{`) and `END_CURLY_REGEXP_LA` (lookahead for `}`). A stack tracks nesting; each closed element is instantiated and stored in a flat hash keyed by a dotted ref path (e.g. `"1234567890.1.2"`).
|
|
60
|
+
|
|
61
|
+
### Elements (`lib/mps/elements/`)
|
|
62
|
+
Each element type (Task, Note, Reminder, Log, MPS) is a class that `include`s the `MPS::Element` mixin. The mixin provides `initialize(args:, refs:, body_str:)`, `display_str`, and `attr_reader :body_str`. Each class must define `SIGNATURE_STAMP` (used when generating filenames/wrapping) and `SIGNATURE_REGEX` (matched against the parsed element sign to dispatch). The engine discovers all element classes dynamically via `MPS::Elements.constants`.
|
|
63
|
+
|
|
64
|
+
### Interpolators (`lib/mps/interpolators/`)
|
|
65
|
+
Interpolator classes (e.g. `Interpolators::Time`) are discovered the same way as elements — via `const_get` on the module's `constants`. Each defines `SIGNATURE_REGEX` and `get_str(**ref)`. They are loaded into `Engines::MPS` but the interpolation call-site is not yet wired up in the engine.
|
|
66
|
+
|
|
67
|
+
### Configuration (`lib/mps/config.rb` + `lib/mps/constants.rb`)
|
|
68
|
+
`Config.init(path)` writes a default YAML config. `Config.new(**hash)` holds `storage_dir`, `mps_dir`, `log_file`, and a `Logger`. Two additional optional YAML keys are supported: `git_remote` (default `"origin"`) and `git_branch` (default `"master"`); both are exposed as `attr_reader`s and used by `git` and `autogit` commands. The CLI re-reads the config on every invocation via `load_config`; it auto-creates missing directories and the log file.
|
|
69
|
+
|
|
70
|
+
## File format
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
@task[tag1, tag2]{
|
|
74
|
+
Task body text
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@note{
|
|
78
|
+
Free-form note
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@reminder[at: 3pm]{
|
|
82
|
+
Meeting description
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@log[start: 09:00, end: 12:30]{
|
|
86
|
+
Time log entry
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@mps{
|
|
90
|
+
@task{ nested task }
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
File names follow `YYYYMMDD.<epoch>.mps`; the epoch disambiguates multiple files per day. The regexp for valid names is `Constants::MPS_FILE_NAME_REGEXP`.
|
|
95
|
+
|
|
96
|
+
## Testing
|
|
97
|
+
|
|
98
|
+
Tests use Minitest with `fakefs` for filesystem isolation. The test helper at `test/test_helper.rb` sets up the load path and does `include MPS`, so all constants and module methods are available directly in test classes.
|
|
99
|
+
|
|
100
|
+
`test/engine_test.rb` tests the parser directly: it uses a `parse_content(str)` helper that writes a fixture file under `FakeFS` at `/tmp/20260101.mps` and calls `Engines::MPS.parse_mps_file_to_elments_hash` on it. Covers empty files, single and multiple elements, unknown element fallback to `Struct`, nested `@mps{}`, `matched_element_class`, and `look_ahead_pos` edge cases.
|
|
101
|
+
|
|
102
|
+
`test/config_test.rb` covers `Config.init`, `Config.load_conf_hash` (including `git_remote`/`git_branch` defaults), logger formatting, and `LoadError` on missing keys.
|
data/GETTING_STARTED.md
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
# Getting Started with MPS
|
|
2
|
+
|
|
3
|
+
MPS is a plain-text productivity system that lives in your terminal. Your tasks, notes, reminders, and logs are just `.mps` files in a folder — readable, portable, and git-backed. No app to install, no account to create, no sync service to trust.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
gem install mps
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
First run creates everything automatically:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
~/.mps_config.yaml ← your config
|
|
17
|
+
~/.mps/mps/ ← where your files live
|
|
18
|
+
~/.mps/mps.log ← activity log
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## The file format
|
|
24
|
+
|
|
25
|
+
Before anything else, it helps to know what you're working with. Each `.mps` file is plain text. Every entry is an **element** — a type, optional arguments in `[]`, and a body in `{}`:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
@task[work, release]{
|
|
29
|
+
Ship the API refactor
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@note{
|
|
33
|
+
The auth token expiry edge case needs a second look
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@reminder[at: 10am]{
|
|
37
|
+
Team standup
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@log[start: 09:00, end: 12:30]{
|
|
41
|
+
Debugging the auth flow
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@mps{
|
|
45
|
+
@task[backend]{
|
|
46
|
+
Nested task inside a sub-block
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The brackets are optional — `@task{ body }` is perfectly valid. Elements nest freely. Files are named `YYYYMMDD.<epoch>.mps` — the epoch allows multiple files per day without collision.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## A day in the life
|
|
56
|
+
|
|
57
|
+
It's Monday morning. You open your terminal:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
mps
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Vim opens with today's file — `20260428.1745000000.mps`. You write your morning plan, save, and quit. That's your day started.
|
|
64
|
+
|
|
65
|
+
If you want a specific date instead:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
mps open yesterday
|
|
69
|
+
mps open "last monday"
|
|
70
|
+
mps open 20260421
|
|
71
|
+
mps open "2 days ago"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Natural language dates work everywhere in MPS, powered by [Chronic](https://github.com/mojombo/chronic). Anything Chronic understands, MPS understands.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Reading what you wrote
|
|
79
|
+
|
|
80
|
+
You're two hours into the day and forget whether you wrote down that reminder. Don't open Vim — just ask:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
mps list
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
[task] (open) Review the API pull request [work]
|
|
88
|
+
[reminder] (10am) Team standup
|
|
89
|
+
[note] The auth token expiry edge case needs a second look
|
|
90
|
+
[@mps]
|
|
91
|
+
[task] (open) Nested backend task [backend]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The nested tree is preserved — child elements appear indented under their parent `[@mps]` group. Each type gets its own color in the terminal.
|
|
95
|
+
|
|
96
|
+
### Filter by type
|
|
97
|
+
|
|
98
|
+
Only want tasks?
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
mps list --type task
|
|
102
|
+
# short form:
|
|
103
|
+
mps list -t task
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Filter by tag
|
|
107
|
+
|
|
108
|
+
Everything tagged `work`:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
mps list --tag work
|
|
112
|
+
mps list -g work
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Filter by status (tasks only)
|
|
116
|
+
|
|
117
|
+
See only what's still open:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
mps list --status open
|
|
121
|
+
mps list -s done
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Status filtering only applies to tasks — notes, logs, and reminders are excluded when you use `--status`.
|
|
125
|
+
|
|
126
|
+
### Look at a different day
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
mps list yesterday
|
|
130
|
+
mps list "last friday"
|
|
131
|
+
mps list 20260421
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Date ranges with `--since`
|
|
135
|
+
|
|
136
|
+
Want everything from the last week up to today?
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
mps list --since "last monday"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
This prints a date header for each day that has entries:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
── 2026-04-25 ─────────────
|
|
146
|
+
[task] (done) Set up CI pipeline [devops]
|
|
147
|
+
── 2026-04-28 ─────────────
|
|
148
|
+
[task] (open) Review the API pull request [work]
|
|
149
|
+
[note] Token expiry edge case
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Combine filters freely: `mps list --since yesterday --type task --status open` shows all open tasks from yesterday to today.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Quick-capture without opening Vim
|
|
157
|
+
|
|
158
|
+
You're deep in a debugging session. A thought hits you. You don't want to break your flow:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
mps append note "Check if the race condition only happens under load"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
appended [note] Check if the race condition only happens under load
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The note lands at the bottom of today's file.
|
|
169
|
+
|
|
170
|
+
### Append with tags
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
mps append task "Fix the token expiry bug" --tags work,backend
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Append a task with status
|
|
177
|
+
|
|
178
|
+
Already done? Mark it immediately:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
mps append task "Reviewed the PR" --tags work --status done
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Log your time
|
|
185
|
+
|
|
186
|
+
Log a focused work session with start and end times:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
mps append log "Deep work on auth refactor" --tags work --start-time 09:00 --end-time 12:30
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The 3h30m duration is computed automatically and shown in `list`, `stats`, and `export`.
|
|
193
|
+
|
|
194
|
+
### Set a timed reminder
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
mps append reminder "Push the hotfix before EOD" --at "5pm"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
All types supported by `append`: `task`, `note`, `log`, `reminder`.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Search across all your files
|
|
205
|
+
|
|
206
|
+
End of quarter. You vaguely remember logging something about "auth" in March. You don't know which file.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
mps search "auth"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
2026-04-28 [log] (3h30m) Debugging the auth flow [work, backend]
|
|
214
|
+
2026-04-21 [task] (done) Fix auth token expiry [backend]
|
|
215
|
+
(2 results)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Every `.mps` file in your storage directory is searched. Results show the date, type badge, and first line of the body.
|
|
219
|
+
|
|
220
|
+
### Narrow the search
|
|
221
|
+
|
|
222
|
+
Filter to a specific type:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
mps search "auth" --type log
|
|
226
|
+
mps search "auth" -t task
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Filter to a tag:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
mps search "auth" --tag backend
|
|
233
|
+
mps search "auth" -g work
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Limit to recent files:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
mps search "auth" --since "last month"
|
|
240
|
+
mps search "auth" -S "2026-04-01"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
All filters compose: `mps search "auth" --type task --tag backend --since "last week"`.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Your productivity at a glance
|
|
248
|
+
|
|
249
|
+
Friday afternoon. How did your week go?
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
mps stats --since monday
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
2026-04-25 — 2 tasks (1 open, 1 done), 1 note, 1 log (2h)
|
|
257
|
+
2026-04-26 — 1 task (0 open, 1 done), 2 logs (5h30m)
|
|
258
|
+
2026-04-28 — 3 tasks (2 open, 1 done), 1 note, 1 reminder, 1 log (3h30m)
|
|
259
|
+
────────────────────────────────────────────────
|
|
260
|
+
Total: 6 tasks, 3 notes, 1 reminder, 3 logs (11h total)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Open vs done task counts, total logged hours, everything in one view.
|
|
264
|
+
|
|
265
|
+
For a single day:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
mps stats
|
|
269
|
+
mps stats yesterday
|
|
270
|
+
mps stats 20260421
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Export your data
|
|
276
|
+
|
|
277
|
+
Need to feed your `.mps` data into a spreadsheet, script, or another tool?
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
mps export --format json
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
[
|
|
285
|
+
{
|
|
286
|
+
"date": "2026-04-28",
|
|
287
|
+
"ref": "1745000000.1",
|
|
288
|
+
"type": "task",
|
|
289
|
+
"tags": "work",
|
|
290
|
+
"body": "Review the API pull request",
|
|
291
|
+
"status": "open"
|
|
292
|
+
},
|
|
293
|
+
...
|
|
294
|
+
]
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
CSV format:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
mps export --format csv
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
date,ref,type,tags,body,status,at,start,end
|
|
305
|
+
2026-04-28,1745000000.1,task,work,Review the API pull request,open,,,
|
|
306
|
+
2026-04-28,1745000000.2,reminder,,Team standup,,10am,,
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
All the same filters apply:
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Export all tasks this week
|
|
313
|
+
mps export --since monday --type task --format csv > this_week_tasks.csv
|
|
314
|
+
|
|
315
|
+
# Export everything from a specific day as JSON
|
|
316
|
+
mps export 20260421 --format json > april21.json
|
|
317
|
+
|
|
318
|
+
# Pipe into jq
|
|
319
|
+
mps export --since "last month" --format json | jq '[.[] | select(.status == "done")]'
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Git backup — one command
|
|
325
|
+
|
|
326
|
+
Your files live in `~/.mps/mps/`. Initialize that directory as a git repo once, then let MPS handle sync:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
mps autogit
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
This does: `git add .` → `git commit -m "$(date)"` → `git pull` → `git push`. Run it at the end of each day.
|
|
333
|
+
|
|
334
|
+
For manual control:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
mps git status
|
|
338
|
+
mps git log --oneline -5
|
|
339
|
+
mps git commit -m "end of sprint retrospective"
|
|
340
|
+
mps git auto # same as autogit
|
|
341
|
+
mps git autocommit # stage and commit only, no push
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Every `mps git` command runs inside your storage directory — no `cd` needed.
|
|
345
|
+
|
|
346
|
+
### Configure your remote and branch
|
|
347
|
+
|
|
348
|
+
By default MPS pushes to `origin` on `master`. To use a different remote or branch, edit `~/.mps_config.yaml`:
|
|
349
|
+
|
|
350
|
+
```yaml
|
|
351
|
+
mps_dir: /home/you/.mps
|
|
352
|
+
storage_dir: /home/you/.mps/mps
|
|
353
|
+
log_file: /home/you/.mps/mps.log
|
|
354
|
+
git_remote: origin
|
|
355
|
+
git_branch: main
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Run any shell command in your storage directory
|
|
361
|
+
|
|
362
|
+
Need to see what files exist, or grep across everything raw?
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
mps cmd ls -la
|
|
366
|
+
mps cmd grep -r "token expiry" .
|
|
367
|
+
mps cmd wc -l *.mps
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Everything runs inside `~/.mps/mps/`.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Version
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
mps version
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Full reference
|
|
383
|
+
|
|
384
|
+
### Commands
|
|
385
|
+
|
|
386
|
+
| Command | What it does |
|
|
387
|
+
|---------|-------------|
|
|
388
|
+
| `mps` / `mps open [date]` | Open a date's file in Vim (default: today) |
|
|
389
|
+
| `mps list [date]` | Print elements in tree order (default: today) |
|
|
390
|
+
| `mps append TYPE BODY` | Add one element to today's file without Vim |
|
|
391
|
+
| `mps search QUERY` | Full-text search across all files |
|
|
392
|
+
| `mps stats [date]` | Element counts and log durations for a date |
|
|
393
|
+
| `mps export [date]` | Export elements as JSON or CSV to stdout |
|
|
394
|
+
| `mps autogit` | Stage, commit, pull, push in one shot |
|
|
395
|
+
| `mps git ARGS` | Run any git command inside storage dir |
|
|
396
|
+
| `mps cmd ARGS` | Run any shell command inside storage dir |
|
|
397
|
+
| `mps version` | Print current version |
|
|
398
|
+
|
|
399
|
+
### list options
|
|
400
|
+
|
|
401
|
+
| Option | Short | Description |
|
|
402
|
+
|--------|-------|-------------|
|
|
403
|
+
| `--type TYPE` | `-t` | Filter by: `task`, `note`, `log`, `reminder` |
|
|
404
|
+
| `--tag TAG` | `-g` | Filter by tag name |
|
|
405
|
+
| `--status STATUS` | `-s` | Filter tasks by: `open`, `done` |
|
|
406
|
+
| `--since DATESIGN` | `-S` | Show elements from SINCE up to DATESIGN |
|
|
407
|
+
|
|
408
|
+
### append options
|
|
409
|
+
|
|
410
|
+
| Option | Description |
|
|
411
|
+
|--------|-------------|
|
|
412
|
+
| `--tags t1,t2` | Comma-separated tags |
|
|
413
|
+
| `--status open\|done` | Task status (default: open) |
|
|
414
|
+
| `--at TIME` | Time for reminders (e.g. `5pm`) |
|
|
415
|
+
| `--start-time HH:MM` | Start time for logs |
|
|
416
|
+
| `--end-time HH:MM` | End time for logs |
|
|
417
|
+
|
|
418
|
+
### search options
|
|
419
|
+
|
|
420
|
+
| Option | Short | Description |
|
|
421
|
+
|--------|-------|-------------|
|
|
422
|
+
| `--type TYPE` | `-t` | Filter by element type |
|
|
423
|
+
| `--tag TAG` | `-g` | Filter by tag |
|
|
424
|
+
| `--since DATESIGN` | `-S` | Search from this date onward |
|
|
425
|
+
|
|
426
|
+
### stats options
|
|
427
|
+
|
|
428
|
+
| Option | Short | Description |
|
|
429
|
+
|--------|-------|-------------|
|
|
430
|
+
| `--since DATESIGN` | `-S` | Stats from SINCE up to DATESIGN |
|
|
431
|
+
|
|
432
|
+
### export options
|
|
433
|
+
|
|
434
|
+
| Option | Short | Description |
|
|
435
|
+
|--------|-------|-------------|
|
|
436
|
+
| `--format FORMAT` | `-f` | Output format: `json` (default), `csv` |
|
|
437
|
+
| `--type TYPE` | `-t` | Filter by element type |
|
|
438
|
+
| `--since DATESIGN` | `-S` | Export from SINCE up to DATESIGN |
|
|
439
|
+
|
|
440
|
+
### Date formats accepted everywhere
|
|
441
|
+
|
|
442
|
+
| Input | Meaning |
|
|
443
|
+
|-------|---------|
|
|
444
|
+
| `today`, `yesterday` | Relative day |
|
|
445
|
+
| `monday`, `last friday` | Day of week |
|
|
446
|
+
| `2 days ago`, `last week` | Natural language |
|
|
447
|
+
| `20260421` | Explicit YYYYMMDD |
|
data/Gemfile
ADDED
data/IMPROVEMENTS.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# MPS Improvements & Feature Roadmap
|
|
2
|
+
|
|
3
|
+
## Bugs
|
|
4
|
+
|
|
5
|
+
| # | File | Issue | Severity |
|
|
6
|
+
|---|------|-------|----------|
|
|
7
|
+
| B1 | `lib/mps/elements/*.rb` | `# frozen string_literal: true` missing the `_` — magic comment is silently ignored | Medium |
|
|
8
|
+
| B2 | `lib/cli/mps.rb:61` | `git pull orign master` — typo `orign` instead of `origin` | High |
|
|
9
|
+
| B3 | `lib/mps/engines/mps.rb:12` | Uses `eval("::MPS::Elements::#{k}")` — unsafe; use `const_get` | Medium |
|
|
10
|
+
| B4 | `test/config_test.rb` | All test bodies are commented out — zero test coverage on Config | High |
|
|
11
|
+
| B5 | `lib/mps/interpolators/` | Interpolators are loaded into `Engines::MPS` but never invoked anywhere | Medium |
|
|
12
|
+
|
|
13
|
+
## Code Quality
|
|
14
|
+
|
|
15
|
+
| # | Issue | Fix |
|
|
16
|
+
|---|-------|-----|
|
|
17
|
+
| Q1 | `ir()` is defined as a bare global method in `lib/mps/mps.rb` — pollutes `Object` | Move inside `MPS` module as `MPS.ir` or keep but at least document it |
|
|
18
|
+
| Q2 | Element classes are identical boilerplate — only `SIGNATURE_STAMP` / `SIGNATURE_REGEX` differ | Extract a `MPS::Elements.define(stamp)` factory or use a shared DSL |
|
|
19
|
+
| Q3 | `Engines::MPS` class name clashes with `Elements::MPS` class — confusing namespace | Rename engine to `Engines::Parser` |
|
|
20
|
+
| Q4 | `Exception` is rescued in every CLI command instead of `StandardError` — catches `SignalException`, `SystemExit` | Use `StandardError` |
|
|
21
|
+
| Q5 | Config is re-read on every CLI invocation but never cached or validated beyond key presence | Add type-checked struct |
|
|
22
|
+
|
|
23
|
+
## New Features
|
|
24
|
+
|
|
25
|
+
### F1 — `list` command
|
|
26
|
+
Display parsed elements from any `.mps` file in the terminal, with optional type filter.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
mps list # today's file
|
|
30
|
+
mps list yesterday # yesterday's file
|
|
31
|
+
mps list 20260226 --type task
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### F2 — `search` command
|
|
35
|
+
Full-text search across all `.mps` files in storage, return matching elements.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
mps search "meeting"
|
|
39
|
+
mps search "deploy" --type task --since 7.days.ago
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### F3 — `stats` command
|
|
43
|
+
Print a summary of element counts per type for a date (or range).
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
mps stats # today
|
|
47
|
+
mps stats --since last.week
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### F4 — `append` command (non-Vim fast entry)
|
|
51
|
+
Append a single element to today's file without opening Vim.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
mps append task "Write release notes" --tags work,release
|
|
55
|
+
mps append note "Idea: dark mode"
|
|
56
|
+
mps append reminder "Standup" --at "9am"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### F5 — Typed element attribute parsing
|
|
60
|
+
Currently `@log[start: 09:00, end: 12:30]` args are raw strings. Parse them into typed structs so `list`/`stats` can compute duration, countdown to reminder time, etc.
|
|
61
|
+
|
|
62
|
+
### F6 — Export command
|
|
63
|
+
Serialize parsed elements to JSON or CSV.
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
mps export --format json > today.json
|
|
67
|
+
mps export --format csv --since last.week > week.csv
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### F7 — Configurable branch / remote for git sync
|
|
71
|
+
`git auto` hardcodes `master` and `origin`. Make both configurable in `~/.mps_config.yaml`.
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
git_remote: origin
|
|
75
|
+
git_branch: main
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Implementation Priority
|
|
79
|
+
|
|
80
|
+
1. **B1, B2, B3** — straightforward, low-risk fixes
|
|
81
|
+
2. **Q4** — safety (rescue `StandardError` not `Exception`)
|
|
82
|
+
3. **B4** — restore test coverage (Config + Engine parser)
|
|
83
|
+
4. **F1 `list`** — most immediately useful, builds on existing parser
|
|
84
|
+
5. **F4 `append`** — second most useful daily-driver feature
|
|
85
|
+
6. **F7 git config** — removes hardcoded branch/remote
|
|
86
|
+
7. **Q3 rename engine** — minor breaking internal rename
|
|
87
|
+
8. **F5 typed args** — enables F1/F3 to show richer output
|
|
88
|
+
9. **F2 `search`** — builds on F1 infrastructure
|
|
89
|
+
10. **F3 `stats`** — builds on F2
|
|
90
|
+
11. **F6 `export`** — nice-to-have
|