@oh-my-pi/pi-coding-agent 14.6.2 → 14.6.4

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +95 -2
  2. package/README.md +21 -0
  3. package/package.json +23 -7
  4. package/src/cli/grievances-cli.ts +89 -4
  5. package/src/commands/grievances.ts +33 -7
  6. package/src/config/prompt-templates.ts +14 -7
  7. package/src/config/settings-schema.ts +610 -100
  8. package/src/config/settings.ts +42 -0
  9. package/src/discovery/helpers.ts +13 -6
  10. package/src/edit/index.ts +3 -3
  11. package/src/edit/line-hash.ts +73 -25
  12. package/src/edit/modes/hashline.lark +10 -3
  13. package/src/edit/modes/hashline.ts +295 -40
  14. package/src/edit/renderer.ts +3 -3
  15. package/src/hindsight/backend.ts +205 -0
  16. package/src/hindsight/bank.ts +131 -0
  17. package/src/hindsight/client.ts +598 -0
  18. package/src/hindsight/config.ts +175 -0
  19. package/src/hindsight/content.ts +210 -0
  20. package/src/hindsight/index.ts +8 -0
  21. package/src/hindsight/mental-models.ts +382 -0
  22. package/src/hindsight/seeds.json +32 -0
  23. package/src/hindsight/state.ts +469 -0
  24. package/src/hindsight/transcript.ts +71 -0
  25. package/src/main.ts +7 -10
  26. package/src/memories/index.ts +1 -1
  27. package/src/memory-backend/index.ts +4 -0
  28. package/src/memory-backend/local-backend.ts +30 -0
  29. package/src/memory-backend/off-backend.ts +16 -0
  30. package/src/memory-backend/resolve.ts +24 -0
  31. package/src/memory-backend/types.ts +79 -0
  32. package/src/modes/components/settings-defs.ts +50 -451
  33. package/src/modes/components/settings-selector.ts +2 -2
  34. package/src/modes/components/status-line/presets.ts +1 -1
  35. package/src/modes/controllers/command-controller.ts +266 -6
  36. package/src/modes/controllers/event-controller.ts +12 -0
  37. package/src/modes/controllers/selector-controller.ts +3 -12
  38. package/src/modes/theme/theme.ts +4 -0
  39. package/src/prompts/tools/github.md +3 -0
  40. package/src/prompts/tools/hashline.md +21 -16
  41. package/src/prompts/tools/read.md +10 -6
  42. package/src/prompts/tools/recall.md +5 -0
  43. package/src/prompts/tools/reflect.md +5 -0
  44. package/src/prompts/tools/retain.md +5 -0
  45. package/src/prompts/tools/search.md +1 -1
  46. package/src/sdk.ts +21 -9
  47. package/src/session/agent-session.ts +118 -3
  48. package/src/slash-commands/builtin-registry.ts +12 -12
  49. package/src/task/executor.ts +3 -0
  50. package/src/task/index.ts +2 -0
  51. package/src/tools/ast-edit.ts +14 -5
  52. package/src/tools/ast-grep.ts +12 -3
  53. package/src/tools/find.ts +47 -7
  54. package/src/tools/gh-renderer.ts +10 -1
  55. package/src/tools/gh.ts +233 -5
  56. package/src/tools/hindsight-recall.ts +68 -0
  57. package/src/tools/hindsight-reflect.ts +55 -0
  58. package/src/tools/hindsight-retain.ts +60 -0
  59. package/src/tools/index.ts +20 -0
  60. package/src/tools/path-utils.ts +55 -0
  61. package/src/tools/read.ts +1 -1
  62. package/src/tools/search.ts +45 -8
package/CHANGELOG.md CHANGED
@@ -2,7 +2,82 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [14.6.4] - 2026-05-03
6
+ ### Added
7
+
8
+ - Added `hindsight.mentalModelsEnabled`, `hindsight.mentalModelAutoSeed`, `hindsight.mentalModelRefreshIntervalMs`, and `hindsight.mentalModelMaxRenderChars` settings to control curated Hindsight mental-model activation, seeding, refresh cadence, and prompt render budget
9
+ - Added `<mental_models>` injection to developer instructions, loading bank-level curated summaries as stable background context
10
+ - Added built-in `/memory mm` commands (`list`, `show`, `refresh`, `history`, `seed`, `reload`, `delete`) to inspect and manage mental models on the active bank
11
+ - Added scope-aware mental-model seeding for `global`, `per-project`, and `per-project-tagged` banks, including built-in seed models like user preferences, project conventions, and project decisions
12
+ - Added warning output when hashline block replacements auto-absorbed duplicate boundary lines
13
+
14
+ ### Changed
15
+
16
+ - Changed `/memory clear` and `/memory enqueue` to apply only to the current agent session’s Hindsight cache instead of all live Hindsight sessions
17
+ - Changed the prompt assembly order so `<mental_models>` blocks are appended before `<memories>` recall blocks in developer instructions
18
+
19
+ ### Fixed
20
+
21
+ - Fixed Hindsight memory prompt injection and recall/retain tool execution to resolve against the active session state, preventing context from an unrelated session from being used
22
+ - Fixed subagent `/task` sessions to persist memories into the parent agent’s Hindsight bank by explicit parent state wiring
23
+ - Fixed per-session memory retention behavior when switching or resuming sessions by rekeying Hindsight state and resetting conversation-tracking counters so first-turn recall and nth-turn retain cadence no longer leak across conversations
24
+ - Fixed the first-turn startup race so `<mental_models>` appears in the opening system prompt when mental-model loading is enabled
25
+ - Fixed retention hygiene by stripping `<mental_models>` blocks from retained content to prevent curated summaries from feeding back into future memory writes
26
+ - Fixed `<mental_models>` rendering to honor the configured character budget and truncate with an explicit truncation marker when the snapshot exceeds limits
27
+ - Fixed hashline replacements so duplicated payload boundary lines adjacent to a replaced block are absorbed into the replacement range instead of being duplicated
28
+
29
+ ## [14.6.3] - 2026-05-03
30
+
31
+ ### Breaking Changes
32
+
33
+ - Renamed hashline separator configuration from `PI_HASHLINE_SEP` to `PI_HL_SEP` and changed the default payload separator from `\\` to `>`
34
+
35
+ ### Added
36
+
37
+ - Added inline hashline edit syntax so `< ANCHOR${sep}TEXT` prepended text to an anchored line and `+ ANCHOR${sep}TEXT` appended text to it without requiring a multi-line payload block
38
+ - Added a `memory.backend` setting (off, local, hindsight) under a new Memory settings tab to control which memory subsystem is active
39
+ - Added Hindsight memory settings (`hindsight.*`) for API connection, bank identification, and recall/retain policy
40
+ - Added `retain`, `recall`, and `reflect` tools for direct long-term memory search, retention, and reflection when using the Hindsight backend
41
+ - Added `hindsight.scoping` setting (`global`, `per-project`, `per-project-tagged`) that controls whether memories are shared across projects, isolated per cwd, or tagged so global + project memories merge on recall (default: `per-project-tagged`)
42
+ - Added `search_code`, `search_commits`, and `search_repos` ops to the `github` tool so the search surface mirrors `gh search`'s subcommands
43
+
44
+ ### Changed
45
+
46
+ - Changed `hindsight` tool retains to enqueue memory writes and return `Memory queued.` immediately instead of waiting on a network request
47
+ - Changed `hindsight` tool memory writes to use automatic background batching (up to 16 items or 5 seconds) so tool calls do not block
48
+ - Changed failed `hindsight` queue flushes to be surfaced as UI warning notices rather than failing the foreground `hindsight` tool call
49
+ - Changed hashline read/search previews and diff output to keep `|` as the anchor-to-text separator while using the separate configured edit payload separator
50
+ - Mapped invalid `hindsight.scoping` settings back to the default `per-project-tagged` behavior with a warning
51
+ - Changed `/memory view`, `/memory clear`, and `/memory enqueue` to route through the selected memory backend instead of being hardcoded to local memories
52
+ - Changed compaction context assembly to include backend-provided recall context when available
53
+ - Updated multi-path `search`, `find`, `ast-edit`, and `ast-grep` calls to skip missing base paths, returning matches from remaining paths and reporting skipped paths in output
54
+ - Replaced `hindsight.dynamicBankId` (boolean) with the explicit `hindsight.scoping` enum; legacy values are migrated automatically (`dynamicBankId=true` → `scoping="per-project"`)
55
+ - Changed `search_repos` to run as a global repository search using query qualifiers without applying the `repo` filter
56
+
57
+ ### Deprecated
58
+
59
+ - Set explicit `hindsight.scoping` now takes precedence over legacy `hindsight.dynamicBankId` when migrating old settings
60
+
61
+ ### Removed
62
+
63
+ - Removed legacy `hindsight.dynamicBankId` and `hindsight.agentName` fields from the active settings model
64
+ - Removed `hindsight.agentName` and the `HINDSIGHT_AGENT_NAME` / `HINDSIGHT_CHANNEL_ID` / `HINDSIGHT_USER_ID` env vars; the legacy `agent::project::channel::user` bank tuple is gone. A user-set `agentName` is migrated onto `hindsight.bankId`.
65
+
66
+ ### Fixed
67
+
68
+ - Fixed pending `hindsight` queued memory writes to flush on agent end, clear, and enqueue operations so tool-invoked facts are not dropped when sessions transition
69
+ - Fixed retained memory writes from the `hindsight` tool to include session context and tags consistently in background batches
70
+ - Fixed inline hashline modify operations to fail fast when combined with a delete or replace on the same target line
71
+ - Fixed hashline parsing of payload blocks to handle a shared extra leading symbol prefix (such as markdown `>>`) on all payload lines by stripping it as an auto-correction instead of rejecting the edit
72
+ - Forwarded project scoping tags to `hindsight` retain, recall, and reflect operations so manual memory commands honor the active tagging mode
73
+ - Fixed legacy migrations by mapping existing `memories.enabled` values to `memory.backend` on load to preserve prior enable/disable behavior
74
+ - Fixed memory retention so recalled `<memories>` blocks and legacy `<hindsight_memories>` / `<relevant_memories>` blocks are stripped before storing transcripts and do not feed back as new memory
75
+ - Fixed `search_code` output to include each match path, repository, shortened SHA, and a one-line matching fragment
76
+ - Fixed `search_commits` output to show shortened SHAs with commit message first lines
77
+ - Fixed `search_repos` output formatting to return repository summaries including language, stars, forks, issues, visibility, and key status fields
78
+
5
79
  ## [14.6.2] - 2026-05-03
80
+
6
81
  ### Added
7
82
 
8
83
  - Added `statusLine.sessionAccent` to disable session-name accent coloring for the editor border and status line gap ([#918](https://github.com/can1357/oh-my-pi/issues/918))
@@ -13,8 +88,8 @@
13
88
 
14
89
  - Fixed SSH ControlMaster socket paths to use OpenSSH's connection hash (`%C`) so connections to the same host with different users, ports, or jump hosts do not share a master session.
15
90
 
16
-
17
91
  ## [14.6.1] - 2026-05-02
92
+
18
93
  ### Changed
19
94
 
20
95
  - Updated GitHub call headers to display operation-specific titles and contextual metadata such as repository, branch, issue/PR IDs, and search query snippets for supported operations
@@ -25,6 +100,7 @@
25
100
  - Fixed GitHub tool output fallbacks that previously always showed a GitHub Run Watch heading so they now show the actual operation and clear `no output`/`request failed` status messaging
26
101
 
27
102
  ## [14.6.0] - 2026-05-02
103
+
28
104
  ### Breaking Changes
29
105
 
30
106
  - Reworked autoresearch storage and protocol. State now lives in `~/.omp/autoresearch/<project>.db` (SQLite) and per-run logs in `~/.omp/autoresearch/<project>/runs/<id>/benchmark.log`. The repo-side artifacts `autoresearch.md`, `autoresearch.sh`, `autoresearch.checks.sh`, `autoresearch.program.md`, `autoresearch.ideas.md`, `autoresearch.jsonl`, `.autoresearch/`, and `autoresearch.config.json` are no longer read or written; they are deleted by `/autoresearch clear`. Any existing data is not migrated.
@@ -64,6 +140,7 @@
64
140
  - Fixed `log_experiment keep` silently dropping the iteration's diff on an autoresearch branch. The previous logic filtered out every path that was already dirty when `run_experiment` ran — but in the iteration cycle the agent's edits always land before `run_experiment`, so the entire iteration was filtered away and nothing was committed. On an autoresearch branch, `keep` now treats every currently-dirty path as the iteration's change and commits it.
65
141
 
66
142
  ## [14.5.14] - 2026-05-01
143
+
67
144
  ### Changed
68
145
 
69
146
  - Changed markdown conversion and archive tooling to defer loading heavy dependencies (Turndown, fflate, and browser agent content) until first use, reducing startup overhead for CLI startup and command initialization
@@ -105,6 +182,7 @@
105
182
  - Fixed eval startup messaging to report `eval` as unavailable when Python is unreachable and JavaScript backend is disabled
106
183
 
107
184
  ### Fixed
185
+
108
186
  - Stabilized MCP tool ordering so reconnects and refreshes no longer reorder the tools array sent to the model. Anthropic prompt caching is keyed on byte-identical tool definitions; previously, the order depended on connection sequence and a single MCP server reconnect could shuffle tools across servers and invalidate the tools cache breakpoint.
109
187
  - Skipped redundant system-prompt rebuilds in `AgentSession.refreshMCPTools` when the active tool set is unchanged. MCP transport flapping (e.g. routine 5-minute SSE reconnects) used to call `rebuildSystemPrompt` on every reconnect even though the resulting prompt was byte-identical, eating CPU and risking cache misses if the rebuild ever became non-deterministic. The applied-tool signature also covers `customWireName` so a wire-name flip with the rest of the tool metadata constant still forces a rebuild.
110
188
 
@@ -135,6 +213,7 @@
135
213
  - Fixed plan mode to auto-redirect `write` and `edit` calls targeting a bare `PLAN.md` (or any same-basename cwd-relative path) to the canonical `local://PLAN.md` plan artifact instead of rejecting them
136
214
 
137
215
  ## [14.5.11] - 2026-04-30
216
+
138
217
  ### Breaking Changes
139
218
 
140
219
  - `todo_write`: renamed `replace` op to `init` and reshaped its input to `list: [{phase: string, items: string[]}]`. Tasks no longer accept a `status` field; all start `pending` and the first auto-promotes to `in_progress`. The `append` op's `items` is now `string[]` (was `{id, label}[]`)
@@ -206,6 +285,7 @@
206
285
  - Fixed hash mismatch errors to include likely-shifted anchor hints when a unique matching line is found elsewhere in the file
207
286
 
208
287
  ## [14.5.8] - 2026-04-29
288
+
209
289
  ### Breaking Changes
210
290
 
211
291
  - Changed the task runner toggle from `just.enabled` to `runCommand.enabled`, so existing configurations using `just.enabled` must be migrated
@@ -231,12 +311,15 @@
231
311
  ### Fixed
232
312
 
233
313
  - Fixed hook editors to recognize Ctrl+Enter when terminals include NumLock or keypad Enter metadata.
314
+
234
315
  ## [14.5.6] - 2026-04-29
316
+
235
317
  ### Changed
236
318
 
237
319
  - Removed the atom edit mode's multi-anchor auto-rebase rejection so stale-but-uniquely-rebasable block edits apply with warnings instead of failing.
238
320
 
239
321
  ## [14.5.5] - 2026-04-29
322
+
240
323
  ### Breaking Changes
241
324
 
242
325
  - Rejected atom diffs with unrecognized operations (including lone '-' lines) by throwing parse errors instead of treating them as inserts
@@ -255,6 +338,7 @@
255
338
  - Fixed bracket-corruption caused by botched block rewrites by automatically removing a newly introduced duplicate adjacent line when removing it restores the original `{}`, `()`, and `[]` balance and by warning when automatic removal is unsafe
256
339
 
257
340
  ## [14.5.4] - 2026-04-28
341
+
258
342
  ### Breaking Changes
259
343
 
260
344
  - Changed the `atom` edit mode from JSON `{ path, edits }` calls to the compact file-oriented `input` patch language that was previously exposed as `atomd`; `atomd` is no longer a separate edit variant
@@ -308,6 +392,7 @@
308
392
  - Fixed `splice_block` for same-line `(` bodies so inline call sites like `int(port)` can be replaced correctly
309
393
 
310
394
  ## [14.5.2] - 2026-04-26
395
+
311
396
  ### Breaking Changes
312
397
 
313
398
  - Removed support for sed-style string expressions and required `sed` to be specified as an object with `pat` and `rep` (and optional `g`, `F`, `i` flags)
@@ -332,6 +417,7 @@
332
417
  - Removed the hand-rolled JSON unescape fallback in the streaming edit-arg renderer; partial fragments that fail `JSON.parse` are now surfaced raw rather than partially decoded with a non-spec-compliant unescaper that mishandled lone surrogates
333
418
 
334
419
  ## [14.4.3] - 2026-04-26
420
+
335
421
  ### Added
336
422
 
337
423
  - Added `irc` tool for agent-to-agent messaging with `list` and `send` operations, including optional broadcast to `all` and optional suppression of reply waits
@@ -351,6 +437,7 @@
351
437
  - Fixed `/btw` request replacement so issuing a new query cleanly aborts the previous active request
352
438
 
353
439
  ## [14.4.2] - 2026-04-26
440
+
354
441
  ### Breaking Changes
355
442
 
356
443
  - Changed `/todo append` from JSON payload input to `/todo append [<phase>] <task...>` with optional quoted tokens and automatic phase creation
@@ -388,6 +475,7 @@
388
475
  - Fixed `poll` wait duration parsing to fall back to `30s` when the provided value is an empty string
389
476
 
390
477
  ## [14.4.1] - 2026-04-26
478
+
391
479
  ### Breaking Changes
392
480
 
393
481
  - Replaced the legacy `gh_repo_view`, `gh_issue_view`, `gh_pr_view`, `gh_pr_diff`, `gh_pr_checkout`, `gh_pr_push`, `gh_run_watch`, `gh_search_issues`, and `gh_search_prs` tool names with only `github`, which requires updating existing callers that invoked the old `gh_*` tools
@@ -589,6 +677,7 @@
589
677
 
590
678
  - Fixed task calls in `schema-free` and `independent` modes to return clear mode-specific errors when disallowed `context` or `schema` inputs are provided
591
679
  - Fixed newly generated session IDs to use UUIDv7 for new, forked, and branched sessions while preserving resumed session IDs
680
+
592
681
  ## [14.1.1] - 2026-04-14
593
682
 
594
683
  ### Breaking Changes
@@ -630,7 +719,7 @@
630
719
  - Changed Vim page-scroll commands `C-f`, `C-b`, `C-u`, and `C-d` to move in viewport-height based increments instead of fixed constants
631
720
  - Changed `z` command behavior so `zt`, `zb`, and `z.` now align cursor movement to first non-blank in the line
632
721
  - Changed `:g`/`:v` global command handling to process matching lines safely by working in reverse order and preserving file structure
633
- - Changed vim tab breadcrumb rendering from ` → ` to `→` in the editor view
722
+ - Changed vim tab breadcrumb rendering from `→` to `→` in the editor view
634
723
  - Changed custom tool and task execution contexts to no longer expose a shared `searchDb` accessor, removing direct access to native grep/glob/fuzzyFind search backends from extension callbacks
635
724
  - Changed the `task` tool `schema` field to require JSON-encoded JTD schema text instead of a schema object, matching prompt guidance and task-subagent invocation
636
725
  - Changed chunk edit payloads to encode selectors as `path: "file:selector"` and updated chunk tool guidance and examples to match
@@ -664,6 +753,7 @@
664
753
  - Fixed retained Python kernel ownership so `AgentSession.dispose()` only shuts down kernels owned by that session, including warmup-created kernels
665
754
 
666
755
  ## [14.1.0] - 2026-04-11
756
+
667
757
  ### Added
668
758
 
669
759
  - Added richer tool rendering details in session export HTML, including metadata badges, argument formatting, and todo task tree styling for exported tool and workflow messages
@@ -705,6 +795,7 @@
705
795
  - Blocked destructive SQL execution in read-mode SQLite access by using read-only connections and rejecting bound-parameter raw SQL
706
796
 
707
797
  ## [14.0.5] - 2026-04-11
798
+
708
799
  ### Added
709
800
 
710
801
  - Added `designer` model role for UI/UX design tasks with Gemini 3.1 Pro as default model
@@ -751,6 +842,7 @@
751
842
  - Fixed MCP config docs and schema to use `~/.omp/agent/mcp.json` for user-scoped OMP-native MCP config while keeping project config at `<cwd>/.omp/mcp.json`
752
843
 
753
844
  ## [14.0.4] - 2026-04-10
845
+
754
846
  ### Added
755
847
 
756
848
  - Added `PI_CHUNK_AUTOINDENT` environment variable to control whether chunk read/edit tools normalize indentation to canonical tabs or preserve literal file whitespace
@@ -777,6 +869,7 @@
777
869
  - Fixed cached Ollama discovery rows so upgraded installs switch to the OpenAI Responses transport instead of staying on the old completions transport
778
870
 
779
871
  ## [14.0.2] - 2026-04-09
872
+
780
873
  ### Added
781
874
 
782
875
  - Added `/force` slash command to force the next agent turn to use a specific tool
package/README.md CHANGED
@@ -12,3 +12,24 @@ Package-specific references:
12
12
  - [MCP runtime lifecycle](../../docs/mcp-runtime-lifecycle.md)
13
13
  - [MCP server/tool authoring](../../docs/mcp-server-tool-authoring.md)
14
14
  - [DEVELOPMENT](./DEVELOPMENT.md)
15
+
16
+ ## Memory backends
17
+
18
+ The agent supports three mutually-exclusive memory backends, selected via the `memory.backend` setting (Settings → Memory tab, or `~/.omp/config.yml`):
19
+
20
+ - `off` (default) — no memory subsystem runs.
21
+ - `local` — existing rollout-summarisation pipeline; writes `memory_summary.md` and consolidated artifacts under the agent dir.
22
+ - `hindsight` — talks to a [Hindsight](https://hindsight.vectorize.io) server (Cloud or self-hosted Docker), retains transcripts every Nth user turn, recalls memories on the first turn of a session, and exposes `retain`, `recall`, and `reflect`.
23
+
24
+ ### Hindsight quickstart
25
+
26
+ 1. Run a Hindsight server (Cloud or `docker run -p 8888:8888 ghcr.io/vectorize-io/hindsight:latest`).
27
+ 2. Set `memory.backend = "hindsight"` and `hindsight.apiUrl = "http://localhost:8888"` (or your Cloud URL).
28
+ 3. Optional environment overrides (env wins over settings):
29
+ - `HINDSIGHT_API_URL`, `HINDSIGHT_API_TOKEN` — connection
30
+ - `HINDSIGHT_BANK_ID`, `HINDSIGHT_DYNAMIC_BANK_ID`, `HINDSIGHT_AGENT_NAME` — bank addressing
31
+ - `HINDSIGHT_AUTO_RECALL`, `HINDSIGHT_AUTO_RETAIN`, `HINDSIGHT_RETAIN_MODE` — lifecycle
32
+ - `HINDSIGHT_RECALL_BUDGET`, `HINDSIGHT_RECALL_MAX_TOKENS` — recall sizing
33
+ - `HINDSIGHT_BANK_MISSION`, `HINDSIGHT_DEBUG`
34
+
35
+ Switching backends mid-session is honoured on the next system-prompt rebuild and the next `/memory` slash command. Existing users with `memories.enabled = true|false` are migrated to `memory.backend = "local"|"off"` exactly once on first launch.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "14.6.2",
4
+ "version": "14.6.4",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/can1357/oh-my-pi",
7
7
  "author": "Can Boluk",
@@ -46,12 +46,12 @@
46
46
  "dependencies": {
47
47
  "@agentclientprotocol/sdk": "0.20.0",
48
48
  "@mozilla/readability": "^0.6.0",
49
- "@oh-my-pi/omp-stats": "14.6.2",
50
- "@oh-my-pi/pi-agent-core": "14.6.2",
51
- "@oh-my-pi/pi-ai": "14.6.2",
52
- "@oh-my-pi/pi-natives": "14.6.2",
53
- "@oh-my-pi/pi-tui": "14.6.2",
54
- "@oh-my-pi/pi-utils": "14.6.2",
49
+ "@oh-my-pi/omp-stats": "14.6.4",
50
+ "@oh-my-pi/pi-agent-core": "14.6.4",
51
+ "@oh-my-pi/pi-ai": "14.6.4",
52
+ "@oh-my-pi/pi-natives": "14.6.4",
53
+ "@oh-my-pi/pi-tui": "14.6.4",
54
+ "@oh-my-pi/pi-utils": "14.6.4",
55
55
  "@puppeteer/browsers": "^2.13.0",
56
56
  "@sinclair/typebox": "^0.34.49",
57
57
  "@xterm/headless": "^6.0.0",
@@ -371,6 +371,22 @@
371
371
  "types": "./src/memories/*.ts",
372
372
  "import": "./src/memories/*.ts"
373
373
  },
374
+ "./memory-backend": {
375
+ "types": "./src/memory-backend/index.ts",
376
+ "import": "./src/memory-backend/index.ts"
377
+ },
378
+ "./memory-backend/*": {
379
+ "types": "./src/memory-backend/*.ts",
380
+ "import": "./src/memory-backend/*.ts"
381
+ },
382
+ "./hindsight": {
383
+ "types": "./src/hindsight/index.ts",
384
+ "import": "./src/hindsight/index.ts"
385
+ },
386
+ "./hindsight/*": {
387
+ "types": "./src/hindsight/*.ts",
388
+ "import": "./src/hindsight/*.ts"
389
+ },
374
390
  "./modes": {
375
391
  "types": "./src/modes/index.ts",
376
392
  "import": "./src/modes/index.ts"
@@ -19,17 +19,31 @@ export interface ListGrievancesOptions {
19
19
  json: boolean;
20
20
  }
21
21
 
22
- function openDb(): Database | null {
22
+ export interface CleanGrievancesOptions {
23
+ /** Delete a single grievance by id. */
24
+ id?: number;
25
+ /** Delete every grievance recorded for this tool name. */
26
+ tool?: string;
27
+ /** Delete every grievance regardless of tool/id. */
28
+ all?: boolean;
29
+ /** Output the deletion count as JSON instead of a status message. */
30
+ json?: boolean;
31
+ }
32
+
33
+ function openDb(readonly: boolean): Database | null {
23
34
  try {
24
- const db = new Database(getAutoQaDbPath(), { readonly: true });
25
- return db;
35
+ // bun:sqlite rejects `{ readonly: false }` — it requires either readonly,
36
+ // readwrite, or create flags to be explicit. Use the default constructor
37
+ // (readwrite + create) for write mode and only pass `readonly: true` when
38
+ // listing.
39
+ return readonly ? new Database(getAutoQaDbPath(), { readonly: true }) : new Database(getAutoQaDbPath());
26
40
  } catch {
27
41
  return null;
28
42
  }
29
43
  }
30
44
 
31
45
  export async function listGrievances(options: ListGrievancesOptions): Promise<void> {
32
- const db = openDb();
46
+ const db = openDb(true);
33
47
  if (!db) {
34
48
  if (options.json) {
35
49
  console.log("[]");
@@ -76,3 +90,74 @@ export async function listGrievances(options: ListGrievancesOptions): Promise<vo
76
90
  db.close();
77
91
  }
78
92
  }
93
+
94
+ /**
95
+ * Delete grievances from the auto-QA database.
96
+ *
97
+ * Selectors are mutually exclusive in intent — exactly one of `id`, `tool`, or
98
+ * `all` is required. Multiple selectors are rejected to prevent ambiguous deletes
99
+ * (e.g. `--id 5 --all` would be a footgun). Returns silently when the database
100
+ * does not exist yet.
101
+ */
102
+ export async function cleanGrievances(options: CleanGrievancesOptions): Promise<void> {
103
+ const selectors = [options.id !== undefined, !!options.tool, !!options.all].filter(Boolean).length;
104
+ if (selectors === 0) {
105
+ console.error(chalk.red("Specify exactly one of --id, --tool, or --all."));
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+ if (selectors > 1) {
110
+ console.error(chalk.red("--id, --tool, and --all are mutually exclusive."));
111
+ process.exitCode = 1;
112
+ return;
113
+ }
114
+
115
+ const db = openDb(false);
116
+ if (!db) {
117
+ if (options.json) {
118
+ console.log(JSON.stringify({ deleted: 0 }));
119
+ } else {
120
+ console.log(
121
+ chalk.dim("No grievances database found. Enable auto-QA with PI_AUTO_QA=1 or the dev.autoqa setting."),
122
+ );
123
+ }
124
+ return;
125
+ }
126
+
127
+ try {
128
+ let deleted = 0;
129
+ if (options.id !== undefined) {
130
+ const result = db.prepare("DELETE FROM grievances WHERE id = ?").run(options.id);
131
+ deleted = Number(result.changes);
132
+ } else if (options.tool) {
133
+ const result = db.prepare("DELETE FROM grievances WHERE tool = ?").run(options.tool);
134
+ deleted = Number(result.changes);
135
+ } else {
136
+ const result = db.prepare("DELETE FROM grievances").run();
137
+ deleted = Number(result.changes);
138
+ // Reset the autoincrement counter so a fresh slate starts at #1 again.
139
+ // `sqlite_sequence` only exists if AUTOINCREMENT was ever used; ignore failures.
140
+ try {
141
+ db.prepare("DELETE FROM sqlite_sequence WHERE name = 'grievances'").run();
142
+ } catch {
143
+ /* sequence table missing on a brand-new db — nothing to reset */
144
+ }
145
+ }
146
+
147
+ if (options.json) {
148
+ console.log(JSON.stringify({ deleted }));
149
+ return;
150
+ }
151
+
152
+ if (deleted === 0) {
153
+ console.log(chalk.dim("No matching grievances to delete."));
154
+ return;
155
+ }
156
+
157
+ const scope =
158
+ options.id !== undefined ? `#${options.id}` : options.tool ? `for ${options.tool}` : "(all entries)";
159
+ console.log(chalk.green(`Deleted ${deleted} grievance${deleted === 1 ? "" : "s"} ${scope}.`));
160
+ } finally {
161
+ db.close();
162
+ }
163
+ }
@@ -1,20 +1,46 @@
1
1
  /**
2
- * View recently reported tool issues from automated QA.
2
+ * View and clean recently reported tool issues from automated QA.
3
3
  */
4
- import { Command, Flags } from "@oh-my-pi/pi-utils/cli";
5
- import { listGrievances } from "../cli/grievances-cli";
4
+ import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
5
+ import { cleanGrievances, listGrievances } from "../cli/grievances-cli";
6
6
 
7
7
  export default class Grievances extends Command {
8
- static description = "View reported tool issues (auto-QA grievances)";
8
+ static description = "View or clean reported tool issues (auto-QA grievances)";
9
+
10
+ static args = {
11
+ // Positional action: "list" (default) or "clean". A positional arg keeps
12
+ // the historical `omp grievances` invocation working unchanged while
13
+ // reusing the same command surface for the new clean sub-action.
14
+ action: Args.string({
15
+ description: "list (default) or clean",
16
+ required: false,
17
+ options: ["list", "clean"],
18
+ default: "list",
19
+ }),
20
+ };
9
21
 
10
22
  static flags = {
11
- limit: Flags.integer({ char: "n", description: "Number of recent issues to show", default: 20 }),
12
- tool: Flags.string({ char: "t", description: "Filter by tool name" }),
23
+ limit: Flags.integer({ char: "n", description: "Number of recent issues to show (list)", default: 20 }),
24
+ tool: Flags.string({ char: "t", description: "Filter by tool name (list, clean)" }),
13
25
  json: Flags.boolean({ char: "j", description: "Output as JSON", default: false }),
26
+ id: Flags.integer({ description: "Delete a single grievance by id (clean)" }),
27
+ all: Flags.boolean({ description: "Delete every grievance (clean)", default: false }),
14
28
  };
15
29
 
30
+ static examples = [
31
+ "omp grievances",
32
+ "omp grievances list --tool find",
33
+ "omp grievances clean --id 209",
34
+ "omp grievances clean --tool find",
35
+ "omp grievances clean --all",
36
+ ];
37
+
16
38
  async run(): Promise<void> {
17
- const { flags } = await this.parse(Grievances);
39
+ const { args, flags } = await this.parse(Grievances);
40
+ if (args.action === "clean") {
41
+ await cleanGrievances({ id: flags.id, tool: flags.tool, all: flags.all, json: flags.json });
42
+ return;
43
+ }
18
44
  await listGrievances({ limit: flags.limit, tool: flags.tool, json: flags.json });
19
45
  }
20
46
  }
@@ -8,7 +8,7 @@ import {
8
8
  parseFrontmatter,
9
9
  prompt,
10
10
  } from "@oh-my-pi/pi-utils";
11
- import { computeLineHash, HASHLINE_CONTENT_SEPARATOR } from "../edit/line-hash";
11
+ import { computeLineHash, HL_BODY_SEP, HL_EDIT_SEP } from "../edit/line-hash";
12
12
  import { jtdToTypeScript } from "../tools/jtd-to-typescript";
13
13
  import { parseCommandArgs, substituteArgs } from "../utils/command-args";
14
14
 
@@ -53,10 +53,10 @@ interface HashlineHelperState {
53
53
  byLine: Map<number, HashlineHelperRef>;
54
54
  }
55
55
 
56
- const HASHLINE_HELPER_STATE = Symbol("hashlineHelperState");
56
+ const HL_HELPER_STATE = Symbol("hashlineHelperState");
57
57
 
58
58
  interface HashlineHelperStateHolder {
59
- [HASHLINE_HELPER_STATE]?: HashlineHelperState;
59
+ [HL_HELPER_STATE]?: HashlineHelperState;
60
60
  }
61
61
 
62
62
  function isHelperOptions(value: unknown): value is prompt.HelperOptions {
@@ -78,10 +78,10 @@ function getHashlineHelperState(context: unknown, options: prompt.HelperOptions
78
78
  }
79
79
 
80
80
  const holder = holderTarget as HashlineHelperStateHolder;
81
- if (!holder[HASHLINE_HELPER_STATE]) {
82
- holder[HASHLINE_HELPER_STATE] = { byLine: new Map() };
81
+ if (!holder[HL_HELPER_STATE]) {
82
+ holder[HL_HELPER_STATE] = { byLine: new Map() };
83
83
  }
84
- return holder[HASHLINE_HELPER_STATE];
84
+ return holder[HL_HELPER_STATE];
85
85
  }
86
86
 
87
87
  function isLineNumberArg(value: unknown): boolean {
@@ -156,9 +156,16 @@ prompt.registerHelper("hline", function (this: unknown, ...args: unknown[]): str
156
156
  const { num, ref, text } = formatHashlineRef(lineNum, content);
157
157
  const state = getHashlineHelperState(this, options);
158
158
  rememberHashlineRef(state, num, ref);
159
- return `${ref}${HASHLINE_CONTENT_SEPARATOR}${text}`;
159
+ return `${ref}${HL_BODY_SEP}${text}`;
160
160
  });
161
161
 
162
+ /**
163
+ * {{hsep}} — emit the configured hashline payload separator character.
164
+ * Stays in sync with {@link HL_EDIT_SEP} so edit prompt templates
165
+ * never have to hardcode the payload separator.
166
+ */
167
+ prompt.registerHelper("hsep", (): string => HL_EDIT_SEP);
168
+
162
169
  const INLINE_ARG_SHELL_PATTERN = /\$(?:ARGUMENTS|@(?:\[\d+(?::\d*)?\])?|\d+)/;
163
170
  const INLINE_ARG_TEMPLATE_PATTERN = /\{\{[\s\S]*?(?:\b(?:arguments|ARGUMENTS|args)\b|\barg\s+[^}]+)[\s\S]*?\}\}/;
164
171