@gmickel/gno 2.5.1 → 2.7.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.
Files changed (160) hide show
  1. package/README.md +60 -5
  2. package/assets/skill/README.md +5 -1
  3. package/assets/skill/SKILL.md +80 -4
  4. package/assets/skill/cli-reference.md +132 -2
  5. package/assets/skill/examples.md +30 -0
  6. package/assets/skill/mcp-reference.md +54 -1
  7. package/assets/skill/recipes/capture-and-file.md +6 -0
  8. package/assets/skill/recipes/memory-file-decision.md +6 -0
  9. package/assets/skill/recipes/memory-supersede-fact.md +5 -0
  10. package/assets/skill/recipes/session-evidence-lookup.md +98 -0
  11. package/assets/spa-production.json.gz +0 -0
  12. package/browser-extension/artifacts/{gno-browser-clipper-v2.5.1.zip → gno-browser-clipper-v2.7.0.zip} +0 -0
  13. package/browser-extension/artifacts/gno-browser-clipper-v2.7.0.zip.sha256 +1 -0
  14. package/browser-extension/dist/manifest.json +1 -1
  15. package/package.json +2 -1
  16. package/spec/cli.md +449 -35
  17. package/spec/mcp.md +234 -4
  18. package/spec/output-schemas/ask.schema.json +1 -1
  19. package/spec/output-schemas/capture-receipt.schema.json +4 -1
  20. package/spec/output-schemas/doctor.schema.json +88 -0
  21. package/spec/output-schemas/error.schema.json +11 -2
  22. package/spec/output-schemas/get.schema.json +1 -1
  23. package/spec/output-schemas/mcp-capture-result.schema.json +4 -2
  24. package/spec/output-schemas/memory-remember.schema.json +10 -4
  25. package/spec/output-schemas/multi-get.schema.json +4 -1
  26. package/spec/output-schemas/peek.schema.json +2 -9
  27. package/spec/output-schemas/request-status.schema.json +113 -0
  28. package/spec/output-schemas/resident-status.schema.json +22 -0
  29. package/spec/output-schemas/search-result.schema.json +1 -1
  30. package/spec/output-schemas/search-results.schema.json +1 -1
  31. package/spec/output-schemas/sessions-automation-run.schema.json +46 -0
  32. package/spec/output-schemas/sessions-discovery.schema.json +38 -0
  33. package/spec/output-schemas/sessions-import-receipt.schema.json +156 -0
  34. package/spec/output-schemas/sessions-status.schema.json +432 -0
  35. package/spec/output-schemas/status.schema.json +98 -0
  36. package/src/cli/commands/ask.ts +14 -2
  37. package/src/cli/commands/capture.ts +55 -96
  38. package/src/cli/commands/daemon.ts +41 -0
  39. package/src/cli/commands/doctor.ts +54 -20
  40. package/src/cli/commands/embed.ts +41 -3
  41. package/src/cli/commands/ls.ts +3 -0
  42. package/src/cli/commands/memory.ts +12 -3
  43. package/src/cli/commands/query.ts +5 -0
  44. package/src/cli/commands/request-status.ts +59 -0
  45. package/src/cli/commands/reset.ts +39 -5
  46. package/src/cli/commands/sessions.ts +713 -0
  47. package/src/cli/commands/shared.ts +14 -1
  48. package/src/cli/commands/status.ts +63 -5
  49. package/src/cli/commands/vec.ts +54 -0
  50. package/src/cli/detach.ts +29 -1
  51. package/src/cli/errors.ts +13 -9
  52. package/src/cli/program.ts +441 -2
  53. package/src/cli/session-binding.ts +49 -0
  54. package/src/config/types.ts +8 -0
  55. package/src/core/capture-publish.ts +239 -0
  56. package/src/core/capture-sync.ts +12 -2
  57. package/src/core/host-paths.ts +31 -0
  58. package/src/core/memory-remember.ts +234 -122
  59. package/src/core/memory-types.ts +11 -0
  60. package/src/core/network-boundary-inventory.ts +8 -0
  61. package/src/core/request-receipts.ts +671 -0
  62. package/src/core/shutdown-budget.ts +6 -0
  63. package/src/core/vector-partition-status.ts +52 -0
  64. package/src/embed/backlog.ts +124 -18
  65. package/src/embed/fingerprint.ts +6 -3
  66. package/src/embed/retry.ts +66 -27
  67. package/src/embed/variant-backlog.ts +15 -10
  68. package/src/embed/variant-retry.ts +31 -22
  69. package/src/index.ts +30 -2
  70. package/src/llm/native-worker/dispatcher.ts +2 -0
  71. package/src/llm/native-worker/embedding-identity.ts +42 -0
  72. package/src/llm/native-worker/protocol.ts +1 -0
  73. package/src/llm/types.ts +3 -0
  74. package/src/mcp/context.ts +17 -0
  75. package/src/mcp/http-egress.ts +4 -0
  76. package/src/mcp/http-transport.ts +2 -0
  77. package/src/mcp/resources/index.ts +6 -5
  78. package/src/mcp/tool-descriptions-core.ts +1 -1
  79. package/src/mcp/tools/capture.ts +87 -85
  80. package/src/mcp/tools/index.ts +77 -4
  81. package/src/mcp/tools/memory-remember.ts +8 -1
  82. package/src/mcp/tools/memory-shared.ts +7 -1
  83. package/src/mcp/tools/request-status.ts +73 -0
  84. package/src/mcp/tools/sessions.ts +208 -0
  85. package/src/mcp/tools/status.ts +4 -0
  86. package/src/pipeline/hybrid.ts +37 -7
  87. package/src/pipeline/vsearch.ts +14 -2
  88. package/src/sdk/client.ts +180 -84
  89. package/src/sdk/index.ts +6 -0
  90. package/src/sdk/types.ts +54 -2
  91. package/src/serve/capture-service.ts +98 -32
  92. package/src/serve/config-sync.ts +3 -2
  93. package/src/serve/embed-scheduler.ts +133 -19
  94. package/src/serve/host-path-redaction.ts +79 -0
  95. package/src/serve/public/app.tsx +4 -1
  96. package/src/serve/public/components/CaptureModal.tsx +26 -8
  97. package/src/serve/public/components/sessions/AutomationPanel.tsx +800 -0
  98. package/src/serve/public/components/sessions/ImportReceipt.tsx +238 -0
  99. package/src/serve/public/components/sessions/SessionSearch.tsx +286 -0
  100. package/src/serve/public/components/sessions/SourcesPanel.tsx +541 -0
  101. package/src/serve/public/components/sessions/api.ts +40 -0
  102. package/src/serve/public/globals.built.css +1 -1
  103. package/src/serve/public/hooks/use-api.ts +26 -3
  104. package/src/serve/public/lib/request-intent.ts +77 -0
  105. package/src/serve/public/lib/snippet.tsx +52 -0
  106. package/src/serve/public/lib/workspace-actions.ts +12 -1
  107. package/src/serve/public/lib/workspace-tabs.ts +2 -0
  108. package/src/serve/public/pages/Dashboard.tsx +22 -9
  109. package/src/serve/public/pages/DocView.tsx +25 -6
  110. package/src/serve/public/pages/DocumentEditor.tsx +224 -104
  111. package/src/serve/public/pages/Search.tsx +1 -41
  112. package/src/serve/public/pages/Sessions.tsx +350 -0
  113. package/src/serve/resident-runtime.ts +69 -4
  114. package/src/serve/resident-status.ts +13 -1
  115. package/src/serve/routes/api.ts +476 -147
  116. package/src/serve/routes/sessions.ts +766 -0
  117. package/src/serve/security.ts +9 -0
  118. package/src/serve/server.ts +215 -10
  119. package/src/serve/session-automation.ts +146 -0
  120. package/src/serve/status-model.ts +16 -0
  121. package/src/serve/status.ts +2 -0
  122. package/src/serve/watch-reconciliation-shared.ts +3 -0
  123. package/src/serve/watch-service-events.ts +3 -2
  124. package/src/serve/watch-service-run-flush.ts +35 -2
  125. package/src/serve/watch-service.ts +5 -0
  126. package/src/sessions/archive.ts +348 -0
  127. package/src/sessions/automation-state.ts +444 -0
  128. package/src/sessions/automation-status.ts +239 -0
  129. package/src/sessions/automation.ts +1169 -0
  130. package/src/sessions/binding.ts +105 -0
  131. package/src/sessions/claude-hook.ts +240 -0
  132. package/src/sessions/config.ts +176 -0
  133. package/src/sessions/format.ts +191 -0
  134. package/src/sessions/import-child-env.ts +8 -0
  135. package/src/sessions/import-child.ts +152 -0
  136. package/src/sessions/parsers/claude-code.ts +259 -0
  137. package/src/sessions/parsers/codex.ts +303 -0
  138. package/src/sessions/parsers/hermes.ts +248 -0
  139. package/src/sessions/parsers/openclaw.ts +496 -0
  140. package/src/sessions/parsers/shared.ts +184 -0
  141. package/src/sessions/sanitize.ts +222 -0
  142. package/src/sessions/service.ts +1533 -0
  143. package/src/sessions/setup.ts +477 -0
  144. package/src/sessions/sources.ts +518 -0
  145. package/src/sessions/state.ts +118 -0
  146. package/src/sessions/types.ts +457 -0
  147. package/src/store/migrations/031-runtime-independent-vectors.ts +29 -0
  148. package/src/store/migrations/032-vector-runtime-callers.ts +17 -0
  149. package/src/store/migrations/index.ts +4 -0
  150. package/src/store/sqlite/adapter.ts +76 -16
  151. package/src/store/sqlite/scoped-index.ts +9 -0
  152. package/src/store/types.ts +11 -1
  153. package/src/store/vector/lazy.ts +46 -43
  154. package/src/store/vector/runtime-compat.ts +651 -0
  155. package/src/store/vector/sqlite-vec.ts +20 -2
  156. package/src/store/vector/status.ts +276 -35
  157. package/src/store/vector/types.ts +2 -0
  158. package/src/store/vector/variant-search.ts +71 -23
  159. package/src/store/vector/variants.ts +49 -14
  160. package/browser-extension/artifacts/gno-browser-clipper-v2.5.1.zip.sha256 +0 -1
package/README.md CHANGED
@@ -60,6 +60,7 @@ Everything runs on your machine. Zero telemetry. The three network boundaries ar
60
60
  - your knowledge is split across Markdown, code, PDFs, Office files, and exported mail or transcripts
61
61
  - you want one retrieval layer for the CLI, the browser, MCP, and a Bun/TypeScript SDK
62
62
  - you want your coding agent to have a real memory without shipping your docs to a cloud API
63
+ - you want to search what you and your coding agents said in past sessions, kept apart from your curated notes
63
64
  - you need to prove, later, which bytes supported a conclusion
64
65
 
65
66
  ## Two minutes, end to end
@@ -118,7 +119,7 @@ gno daemon --detach # headless indexing + resident MCP gateway
118
119
 
119
120
  **Start here** · [Quick Start](#quick-start) · [Installation](#installation) · [Agent Integration](#agent-integration) · [Search Modes](#search-modes)
120
121
 
121
- **Surfaces** · [Web UI](#web-ui) · [Omarchy Plugin](#omarchy-plugin) · [REST API](#rest-api) · [SDK](#sdk) · [Daemon Mode](#daemon-mode) · [Publish to gno.sh](#publish-to-gnosh)
122
+ **Surfaces** · [Agent Sessions](#agent-sessions) · [Web UI](#web-ui) · [Omarchy Plugin](#omarchy-plugin) · [REST API](#rest-api) · [SDK](#sdk) · [Daemon Mode](#daemon-mode) · [Publish to gno.sh](#publish-to-gnosh)
122
123
 
123
124
  **Under the hood** · [How It Works](#how-it-works) · [Features](#features) · [Local Models](#local-models) · [Fine-Tuned Models](#fine-tuned-models) · [Architecture](#architecture) · [Development](#development)
124
125
 
@@ -138,12 +139,18 @@ See the [guide](docs/COMPILED-CONTEXT.md).
138
139
 
139
140
  <!-- public-truth:current-version -->
140
141
 
141
- > Current source version: **v2.5.1**. See [CHANGELOG.md](./CHANGELOG.md).
142
+ > Current source version: **v2.7.0**. See [CHANGELOG.md](./CHANGELOG.md).
142
143
 
143
144
  <!-- /public-truth -->
144
145
 
145
146
  > Full release history: [CHANGELOG.md](./CHANGELOG.md)
146
147
 
148
+ - **Agent session search** (unreleased): `gno sessions` imports selected local
149
+ Codex, Claude Code, OpenClaw, and Hermes conversations into a dedicated,
150
+ redacted archive with speaker labels and provenance. Imports are manual
151
+ by default; an opt-in Claude Code SessionEnd hook and daemon schedule can
152
+ keep the archive current. Search runs on the archive's own config/index
153
+ pair. See [Agent Sessions](docs/SESSIONS.md).
147
154
  - **Cheap peek snapshot**: `gno peek --json` and MCP `gno_peek` return a
148
155
  model-free `peek@1.0` snapshot (document/collection counts, embedding backlog,
149
156
  10 recent docs with `docid` and `absPath`, pid-file serve detection).
@@ -712,9 +719,10 @@ Connect GNO to Claude Desktop, Cursor, Raycast, and more:
712
719
 
713
720
  ![GNO MCP](./assets/screenshots/mcp.jpg)
714
721
 
715
- GNO exposes 33 tools by default via [Model Context Protocol](https://modelcontextprotocol.io),
722
+ GNO exposes 37 tools by default via [Model Context Protocol](https://modelcontextprotocol.io),
716
723
  including the core retrieval tools below. Starting MCP with `--enable-write`
717
- adds 18 opt-in mutation tools, for 51 total.
724
+ adds 21 opt-in mutation tools and the read-only `gno_request_status` lookup,
725
+ for 59 total.
718
726
 
719
727
  | Tool | Description |
720
728
  | :------------------- | :---------------------------------------------- |
@@ -757,6 +765,50 @@ enables mutation tools.
757
765
 
758
766
  ---
759
767
 
768
+ ## Agent Sessions
769
+
770
+ Make past conversations with Codex, Claude Code, OpenClaw, and Hermes
771
+ searchable without mixing them into your curated notes. GNO reads the local
772
+ session stores (never writes to them), keeps human and assistant turns
773
+ apart, redacts common credential shapes, and writes one sanitized JSONL file
774
+ per thread into an archive you own. Nothing is imported until you ask.
775
+
776
+ ```bash
777
+ # Preview what is on this machine (imports nothing)
778
+ gno sessions discover
779
+
780
+ # One dedicated config + named index for the archive
781
+ gno --config ~/gno-sessions/archive.yml --index sessions \
782
+ sessions init --archive ~/gno-sessions/archive --collection sessions-work
783
+ gno --config ~/gno-sessions/archive.yml --index sessions \
784
+ sessions source add codex --harness codex --path ~/.codex/sessions --collection sessions-work
785
+
786
+ # Dry run, then import (rerun any time; unchanged sessions are skipped)
787
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --dry-run
788
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex
789
+
790
+ # Search what people said, in one harness
791
+ gno --config ~/gno-sessions/archive.yml --index sessions \
792
+ query "why did we pick sqlite" --category harness/codex --author human
793
+
794
+ # Optional: keep it current (off until you enable it; imports run in gno daemon)
795
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation set codex --source codex
796
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation enable codex --schedule --cadence 1h
797
+ gno --config ~/gno-sessions/archive.yml --index sessions daemon --detach
798
+ ```
799
+
800
+ Imported turns are evidence, not facts: assistant turns stay labelled as
801
+ assistant output, and nothing is promoted to `gno remember` automatically.
802
+ Automation is opt-in per profile: a Claude Code SessionEnd hook or a daemon
803
+ schedule marks work pending and `gno daemon` on the archive imports it through
804
+ the same importer; nothing installs or starts a service. Status, import,
805
+ automation runs, and receipts are also available through MCP, REST, the SDK,
806
+ and a `/sessions` Web UI page on a server started with the archive pair.
807
+ Redaction is best effort; see [Agent Sessions](docs/SESSIONS.md) for the
808
+ support matrix, privacy boundary, recovery, and opt-in mixed retrieval.
809
+
810
+ ---
811
+
760
812
  ## Web UI
761
813
 
762
814
  Visual dashboard for search, browsing, editing, and AI answers. Right in your browser.
@@ -777,6 +829,7 @@ Open `http://localhost:3000` to:
777
829
  - **Capture with provenance**: `gno capture` and Web UI Quick Capture write quick notes to an editable collection with structured `source:` metadata, typed preset scaffolds, and a receipt that separates write, sync, and embed state
778
830
  - **Same capture contract everywhere**: CLI, MCP `gno_capture`, REST `/api/capture`, SDK `client.capture()`, and Web UI Quick Capture return the same provenance receipt shape
779
831
  - **Agent memory**: `gno remember` / `gno recall` (also MCP, REST, SDK) store single facts with explicit scopes and supersession, and return budgeted, cited recall with a fencing receipt. See [Memory](docs/MEMORY.md).
832
+ - **Agent sessions**: on a server started with a session-archive config/index pair, `/sessions` manages sources, previews and runs manual imports, and searches sessions with Human/Assistant badges. See [Agent Sessions](docs/SESSIONS.md).
780
833
  - **Browser clipper**: npm-distributed unpacked Chromium extension for explicit
781
834
  visible selection or Reader capture through a local preview/confirm flow.
782
835
  See [Browser Clipper](docs/integrations/browser-clipper.md).
@@ -1076,10 +1129,11 @@ graph TD
1076
1129
  | **Web UI** | Visual dashboard for search, browse, edit, and AI Q&A |
1077
1130
  | **REST API** | HTTP API for custom tools and integrations |
1078
1131
  | **Multi-Format** | Markdown, PDF, Office, JSONL, EML/MBOX, ICS, transcript, and browser exports |
1132
+ | **Agent Sessions** | Manual, redacted import of local coding-agent conversations into a separate archive |
1079
1133
  | **Local LLM** | AI answers via llama.cpp, no API keys |
1080
1134
  | **Remote Inference** | Optional HTTP endpoints for embedding, reranking, expansion, and generation |
1081
1135
  | **Privacy First** | Fail-closed per-collection egress policy; no telemetry; explicit network use |
1082
- | **MCP Server** | 10 automatic client targets; 32 read-only tools, 50 with writes enabled |
1136
+ | **MCP Server** | 10 automatic client targets; 37 read-only tools, 59 with writes enabled |
1083
1137
  | **Integrity Audits** | Offline link, declared-provenance, and freshness reports with stable IDs |
1084
1138
  | **Knowledge Delta** | Bounded metadata history, structural diffs, and dependency impact paths |
1085
1139
  | **Context Capsules** | Deterministic evidence bundles plus saved-file freshness reverification |
@@ -1087,6 +1141,7 @@ graph TD
1087
1141
  | **Private Replay** | Opt-in local traces, explicit qrels, and read-only ranking comparison |
1088
1142
  | **Verified Setup** | Exact lexical activation proof plus portable project-local profiles |
1089
1143
  | **Browser Clipper** | Explicit selection/Reader capture through visible loopback pairing |
1144
+ | **Safe Retries** | Opt-in request IDs: retried captures, facts, and saves replay instead of writing twice |
1090
1145
  | **Collections** | Organize sources with patterns, contexts, and <code>local_only / lan / remote</code> policy |
1091
1146
  | **Tag Filtering** | Frontmatter tags with hierarchical paths, filter via `--tags-any`/`--tags-all` |
1092
1147
  | **Note Linking** | Wiki links, backlinks, related notes, cross-collection navigation |
@@ -132,6 +132,9 @@ walk the model through:
132
132
  - private retrieval traces/replay and Knowledge Delta inspection
133
133
  - project affinity, explainable content boosts, and collection egress policy
134
134
  - JSONL, mail, calendar, transcript, and browser-export source adapters
135
+ - manual agent-session import into a separate archive, opt-in automation
136
+ (Claude Code SessionEnd hook, daemon schedule), and citing session turns as
137
+ evidence rather than facts
135
138
  - provenance-aware browser clipping and typed second-brain capture recipes
136
139
  - tagging, contexts, and per-collection embedding models
137
140
  - publishing notes as gno.sh reader snapshots (`publish export`)
@@ -145,7 +148,8 @@ progressive disclosure — the model only pulls them when it needs them:
145
148
  - [mcp-reference.md](mcp-reference.md) — MCP tool and resource contract
146
149
  - [examples.md](examples.md) — end-to-end usage patterns
147
150
  - [recipes/](recipes/) — task-shaped second-brain workflows for lookup,
148
- capture, meetings, email context, source summaries, ideas, and citations
151
+ capture, meetings, email context, source summaries, ideas, citations,
152
+ memory, and past agent sessions
149
153
 
150
154
  ## Agent tooling contract
151
155
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gno
3
- description: Search local documents, files, notes, and knowledge bases. Index directories, search with BM25/vector/hybrid, get AI answers with citations. Use when user wants to search files, find documents, query notes, look up information in local folders, index a directory, set up document search, build a knowledge base, needs RAG/semantic search, or wants to start a local web UI for their docs.
3
+ description: Search local documents, files, notes, and knowledge bases. Index directories, search with BM25/vector/hybrid, get AI answers with citations. Use when user wants to search files, find documents, query notes, look up information in local folders, index a directory, set up document search, build a knowledge base, needs RAG/semantic search, wants to start a local web UI for their docs, or asks what was said in past coding-agent sessions.
4
4
  allowed-tools: Bash(gno:*) Read
5
5
  ---
6
6
 
@@ -26,6 +26,7 @@ network boundaries.
26
26
  - User asks about **backlinks, wiki links, or related notes**
27
27
  - User wants to **visualize document connections** or see a **knowledge graph**
28
28
  - User wants to **export a note or collection for gno.sh publishing**
29
+ - User asks what was **said or decided in past agent sessions** (Codex, Claude Code, OpenClaw, Hermes)
29
30
 
30
31
  ## Quick Start
31
32
 
@@ -65,6 +66,7 @@ the matching recipe, then run the commands it names.
65
66
  | File a fact that may change | `recipes/memory-file-decision.md` | Fact stored (add) or proposal resolved, cited |
66
67
  | Replace a stale recalled fact | `recipes/memory-supersede-fact.md` | Successor written, predecessor superseded |
67
68
  | What do we know/believe about X | `recipes/memory-scoped-recall.md` | Current facts recalled under budget, cited |
69
+ | What was said/decided in a session | `recipes/session-evidence-lookup.md` | Turns cited with speaker; proposals labelled |
68
70
 
69
71
  Recipe rules:
70
72
 
@@ -92,6 +94,7 @@ Recipe rules:
92
94
  | **Serve** | `serve`, `daemon` | One resident Web/headless gateway and watcher |
93
95
  | **Publish** | `publish export` | Export gno.sh publish artifacts |
94
96
  | **Memory** | `remember`, `recall` | Fact-granular agent memory with explicit scopes and supersession |
97
+ | **Sessions** | `sessions discover/init/source add/source remove/import/status/prune/automation` | Agent-session archive: manual import, opt-in hook/schedule automation |
95
98
  | **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration |
96
99
  | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
97
100
  | **Admin** | `peek`, `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Snapshot, maintenance, and diagnostics |
@@ -127,8 +130,9 @@ Open without fetching content via `gno get`:
127
130
  `#anchor`). Take `serveUrl` from peek `serve.url` when `serve.running` is
128
131
  true.
129
132
  - **Source file**: peek `recent[].absPath`, or search `--json`
130
- `results[].source.absPath`. If `absPath` is absent, show the URI tail and
131
- do not offer file-open for that row.
133
+ `results[].source.absPath`. If `absPath` is absent (always for remote REST
134
+ and HTTP MCP callers), show the URI tail and do not offer file-open for
135
+ that row.
132
136
 
133
137
  ## Search Modes
134
138
 
@@ -554,7 +558,8 @@ Programmatic capture uses the same receipt contract:
554
558
 
555
559
  MCP capture writes structured `source:` frontmatter, runs under the MCP write
556
560
  lock, syncs the file for FTS, and preserves legacy MCP fields (`docid`,
557
- `absPath`, `overwritten`, `serverInstanceId`) alongside the shared receipt. It
561
+ `absPath` over stdio only, `overwritten`, `serverInstanceId`) alongside the
562
+ shared receipt. It
558
563
  does not auto-embed.
559
564
 
560
565
  For an explicit browser capture, use the local unpacked Chromium clipper with
@@ -584,6 +589,77 @@ existing notes. They work only on a collection with `memoryManaged: true`.
584
589
  - Details, error codes, and the fence's paraphrase limit: `docs/MEMORY.md`,
585
590
  [cli-reference.md](cli-reference.md), [mcp-reference.md](mcp-reference.md).
586
591
 
592
+ ## Agent Sessions (separate archive)
593
+
594
+ `gno sessions` imports local Codex, Claude Code, OpenClaw, and Hermes
595
+ conversations into a dedicated archive: its own config file plus a named
596
+ index. Broad search on the user's normal index never includes it, so search
597
+ sessions on the archive pair, and pass both flags on every archive command:
598
+
599
+ ```bash
600
+ gno sessions discover # preview local stores; imports nothing
601
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --dry-run
602
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --json
603
+ gno --config ~/gno-sessions/archive.yml --index sessions search "postgres" --author human --tags-all project/api
604
+ gno --config ~/gno-sessions/archive.yml --index sessions query "why sqlite" --category harness/codex
605
+ ```
606
+
607
+ - Manual by default: discover, then import only when the user asks. Setup
608
+ (on the pair) is `sessions init --archive <dir> --collection <name>`, then
609
+ `sessions source add <id> --harness <h> --path <root> --collection <name>`
610
+ with optional repeatable `--project <prefix>=<collection>`. Keep the
611
+ archive outside the curated vault, one collection per privacy boundary.
612
+ - Filters: `--author human|assistant`, tags `harness/<h>`, `role/<r>`,
613
+ `project/<name>`, `project-id/<hash>`, `session-kind/<k>`, `-c <collection>`.
614
+ Import does not embed; run `embed` on the pair for `query`/`vsearch`.
615
+ - Reruns are incremental. `partial` receipts (`truncated_tail`,
616
+ `format_drift`) retry on the next import; `--limit <n>` defers the rest;
617
+ `SESSIONS_BUSY` means another import runs; `SESSIONS_BINDING_MISMATCH`
618
+ means the config and index were not passed together.
619
+ - Session turns are evidence, not facts. A human turn is what the person
620
+ said; an assistant turn is a proposal, never the user's decision. Cite by
621
+ `gno://` URI (keep `?index=sessions`). Nothing is promoted to
622
+ `remember`/`recall` automatically; store a fact only when asked, with the
623
+ turn's URI as `--source`. Workflow: `recipes/session-evidence-lookup.md`.
624
+ - Automation is opt-in and only on the user's explicit request; installing
625
+ this skill, GNO, or MCP never enables it.
626
+ `sessions automation set <p> --source <id>` creates a profile (nothing
627
+ enabled), `preview <p>` shows the exact hook command, settings file, and
628
+ daemon prerequisite, and `enable <p> --hook claude-code` or
629
+ `enable <p> --schedule --cadence 30m` switches one trigger on.
630
+ Only the Claude Code SessionEnd hook exists; other harnesses use a
631
+ schedule. Triggers only mark work pending: imports run in `gno daemon` on
632
+ the archive pair (never `gno serve`) or with `sessions automation run <p>`.
633
+ - Check automation with `sessions status` (`automation` block: `state`,
634
+ `pending`, `lastRun`, `lastSuccessAt`, `recovery`). A hook that says
635
+ `accepted` has not archived anything yet; `not running: no daemon` means
636
+ start the daemon or run the profile. Repair a missing hook entry by
637
+ re-running `enable --hook claude-code`; pause with `disable <p>`,
638
+ uninstall with `remove <p>` (only GNO's own entry is touched; archives
639
+ stay). `GNO_SESSIONS_HOOKS=off` silences installed hooks.
640
+
641
+ ## Retry-Safe Writes (request IDs)
642
+
643
+ For capture, `remember --add`/`--supersede`, and REST document saves, generate
644
+ one fresh ID (a UUID) per write intent and save it before sending: CLI
645
+ `--request-id <id>`, MCP/REST/SDK `requestId`.
646
+
647
+ ```bash
648
+ gno capture "Launch moved to Oct 3" --request-id 7d0c6f2e-... --json
649
+ gno request-status 7d0c6f2e-... --json # after a timeout or lost response
650
+ ```
651
+
652
+ - Check before retrying (`gno request-status <id>`, MCP `gno_request_status`,
653
+ REST `GET /api/requests/:requestId`, SDK `client.requestStatus(id)`):
654
+ `committed` = done, use `result`, do not resend; `pending` or `not_found` =
655
+ resend the identical call with the same ID; `expired` = it already ran.
656
+ - Never reuse an ID for a changed payload (`REQUEST_ID_CONFLICT`); a new
657
+ intent gets a new ID.
658
+ - `REQUEST_RECOVERY_CONFLICT`, `CONFLICT`, or a predecessor-hash mismatch:
659
+ re-read (`gno get` / `gno recall`) and decide again; never force-overwrite.
660
+ - A request ID is not a recall `receipt`: the receipt fences recalled text,
661
+ the ID identifies one write for retries. Details: [cli-reference.md](cli-reference.md).
662
+
587
663
  ## Reference-Safe Rename and Move
588
664
 
589
665
  When MCP writes are enabled and the user asks to rename or move an editable
@@ -117,9 +117,15 @@ gno collection clear-embeddings <name> [--all] [--json]
117
117
  ### gno embed
118
118
 
119
119
  ```bash
120
- gno embed [collection] [--collection <name>] [--force] [--model <uri>] [--batch-size <n>] [--dry-run]
120
+ gno embed [collection] [--collection <name>] [--force] [--model <uri>] [--batch-size <n>] [--dry-run] [--new-partition]
121
121
  ```
122
122
 
123
+ Switching `GNO_LLAMA_GPU`, Bun version or thread count resumes the existing
124
+ vector partition when a measured sample of stored chunks matches. If it does
125
+ not, embed refuses to build a separate partition without `--new-partition`
126
+ (`--yes` alone never confirms); queries from that runtime fall back to lexical
127
+ retrieval with a `vector_runtime_incompatible` warning.
128
+
123
129
  ## Indexing
124
130
 
125
131
  ### gno update
@@ -150,7 +156,7 @@ gno index [options]
150
156
  Generate embeddings only.
151
157
 
152
158
  ```bash
153
- gno embed [--force] [--model <uri>] [--batch-size <n>] [--dry-run]
159
+ gno embed [--force] [--model <uri>] [--batch-size <n>] [--dry-run] [--new-partition]
154
160
  ```
155
161
 
156
162
  ## Project Profiles
@@ -205,6 +211,8 @@ Important behavior:
205
211
  - `--json` returns a capture receipt with separate write, sync, and embed status.
206
212
  - Capture syncs the file into FTS but does not imply embedding unless
207
213
  `embed.status` is `completed`.
214
+ - `--request-id <id>` makes a retry safe; see
215
+ [Retry-safe writes](#retry-safe-writes-request-ids).
208
216
 
209
217
  ## Memory
210
218
 
@@ -236,6 +244,9 @@ gno remember "..." --scope family --scope shared --collection memory --add --sou
236
244
  `--derived-from gno://...` is rejected. `--source <text>` stores evidence.
237
245
  - `--caller` / `--session` default from `$GNO_MEMORY_CALLER` /
238
246
  `$GNO_MEMORY_SESSION`, then `cli:<user>` / `ppid:<pid>`.
247
+ - `--request-id <id>` needs `--add` or `--supersede`; a candidates-only call
248
+ with an ID is rejected `REQUEST_ID_INVALID`. It is unrelated to
249
+ `--receipt`.
239
250
 
240
251
  ### gno recall
241
252
 
@@ -254,6 +265,124 @@ gno recall "kindergarten" --scope family --max-facts 3 --max-tokens 256 --json >
254
265
  lexical with the reason; recall never downloads a model.
255
266
  - Nothing in scope prints the self-teaching line naming `gno remember`.
256
267
 
268
+ ## Sessions
269
+
270
+ Manual import (plus opt-in automation) of local agent conversations (Codex,
271
+ Claude Code, OpenClaw, Hermes) into a dedicated archive: one config file with a `sessions` block
272
+ plus one named index. Every command except `discover` passes both flags;
273
+ the archive config with another index (or the archive index with another
274
+ config) fails with `SESSIONS_BINDING_MISMATCH`. Full guide: `docs/SESSIONS.md`.
275
+
276
+ ```bash
277
+ gno sessions discover [--json] # preview local stores; never imports
278
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions init --archive ~/gno-sessions/archive --collection sessions-work
279
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions source add codex --harness codex --path ~/.codex/sessions --collection sessions-work --project ~/work/api=sessions-api
280
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --dry-run
281
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --limit 200 --json
282
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import /abs/session.jsonl --collection sessions-work --format codex
283
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions status --json
284
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions prune --source codex [--apply]
285
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions source remove codex # archive kept
286
+
287
+ # Opt-in automation (off until enabled; imports run in `gno daemon` on the pair)
288
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation set claude --source claude-code [--cadence 30m] [--limit 200] [--retries 3]
289
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation preview claude [--json]
290
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation enable claude --hook claude-code [--settings <abs settings.json>]
291
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation enable claude --schedule --cadence 30m
292
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation run claude [--json]
293
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation disable claude [--hook] [--schedule]
294
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions automation remove claude
295
+ gno --config ~/gno-sessions/archive.yml --index sessions daemon --detach
296
+ ```
297
+
298
+ - `--harness`/`--format`: `codex`, `claude-code`, `openclaw`, `hermes`. Paths
299
+ are absolute. `--collection` is for path imports and rejected with
300
+ `--source`.
301
+ - Receipt `status`: `complete`, `partial` (incomplete, failed, unsupported,
302
+ or deferred units; exit 0), `failed` (exit 2), `nothing_to_do`. Reasons
303
+ include `truncated_tail`, `format_drift`, `snapshot_read_failed`,
304
+ `mixed_domain` (quarantined thread), `over_limit`. Reruns are incremental
305
+ and retry incomplete units. Exit 4 = `SESSIONS_BUSY`.
306
+ - Import does not embed: `gno --config … --index sessions embed`.
307
+ - Automation: only the Claude Code SessionEnd hook is supported
308
+ (`SESSIONS_UNSUPPORTED_INTEGRATION` otherwise); cadence `<n>s|m|h|d`, min
309
+ `1m`, elapsed. `sessions hook claude-code --profile <id>` is what the hook
310
+ runs: it prints `accepted (… pending, not yet archived …)`, `skipped`, or
311
+ `not accepted` (exit 2) and never imports. `sessions status` shows the
312
+ `automation` block with `state`, `recovery`, and `not running: no daemon`
313
+ when no daemon on the pair is ticking. Run outcomes: `complete`,
314
+ `up_to_date`, `partial`, `failed`, `not_started`.
315
+ - Search with the normal commands on the pair: `--author human|assistant`,
316
+ `--category harness/<h>`, `--tags-all role/<r>,project/<name>`,
317
+ `-c <collection>`. `--since`/`--until` use import time.
318
+
319
+ ## Retry-safe writes (request IDs)
320
+
321
+ An optional request ID lets a write be retried after a lost response
322
+ (timeout, dropped connection, crash, restart) without a duplicate capture, a
323
+ double supersede, or overwriting a newer document edit. Calls without an ID
324
+ behave as before.
325
+
326
+ | Write | CLI | MCP / REST / SDK field |
327
+ | ---------------------- | ------------------------------------------ | -------------------------------------------------------------------------- |
328
+ | Capture | `gno capture ... --request-id <id>` | `gno_capture`, `POST /api/capture`, `client.capture` `requestId` |
329
+ | Remember add/supersede | `gno remember ... --add --request-id <id>` | `gno_remember`, `POST /api/memory/remember`, `client.remember` `requestId` |
330
+ | Document save/tags | none | REST `PUT /api/docs/:id` body `requestId` |
331
+
332
+ The browser-clipper route `POST /api/capture/clip` keeps its
333
+ `Idempotency-Key` header and rejects `requestId`.
334
+
335
+ IDs are 1-128 characters of letters, digits, `.`, `_`, `:`, `-`, starting with
336
+ a letter or digit; a UUID works.
337
+
338
+ ```bash
339
+ ID=$(uuidgen) # one ID per write intent; save it first
340
+ gno capture "Launch moved to Oct 3" --request-id "$ID" --json
341
+ # response lost? check before retrying:
342
+ gno request-status "$ID" --json
343
+ ```
344
+
345
+ ### gno request-status
346
+
347
+ `gno request-status <request-id> [--json]` (MCP `gno_request_status`
348
+ `{ requestId }`, REST `GET /api/requests/:requestId`, SDK
349
+ `client.requestStatus(id)`). Read-only and content-free: `requestId`,
350
+ `status`, `operation` (`capture` | `remember` | `document.update`),
351
+ timestamps, and for committed requests a `result` with `uri`, `docid`, and
352
+ `contentHash` (or `sourceHash` for a document save).
353
+
354
+ | `status` | Meaning | Next step |
355
+ | ----------- | ------------------------------------------------ | ------------------------------------------ |
356
+ | `committed` | The write finished | Use `result`; do not resend |
357
+ | `pending` | Accepted and written but not finished | Resend the identical call with the same ID |
358
+ | `not_found` | Nothing accepted under this ID | Resend the identical call with the same ID |
359
+ | `expired` | Ran before; full receipt compacted after 30 days | Do not resend; it will not run again |
360
+
361
+ Retry rules:
362
+
363
+ - Identical retry of a committed request replays the stored outcome with
364
+ `request.replayed: true`; nothing is written again. Retrying a `pending`
365
+ request with the same ID finishes the recorded write instead of writing
366
+ again. Retrying with a new ID is a new write; do not.
367
+ - Successful writes sent with an ID include
368
+ `request: { requestId, status, replayed, committedAt }`; CLI text prints
369
+ `Request: <id> committed`.
370
+ - Never reuse an ID for a changed payload, destination, revision, or
371
+ predecessor: `REQUEST_ID_CONFLICT`. New intent, new ID.
372
+ - `REQUEST_RECOVERY_CONFLICT` (the interrupted target changed on disk),
373
+ `CONFLICT` (document revision moved), `MEMORY_PREDECESSOR_HASH_MISMATCH`, or
374
+ `MEMORY_SUPERSEDE_CONFLICT`: re-read with `gno get` or `gno recall` and
375
+ decide again. Never force-overwrite.
376
+ - `REQUEST_PENDING` (exit 4): another caller is still executing it; retry the
377
+ same ID later. `REQUEST_EXPIRED`: do not resend.
378
+ - A rejected write (validation, stale hash, conflict) records nothing, so
379
+ status reads `not_found` and a same-ID retry re-evaluates current state.
380
+ - Request IDs are not recall receipts: `--receipt` / `receipt` fences recalled
381
+ text; `requestId` identifies one write for retries.
382
+ - Other codes: `REQUEST_ID_INVALID`, `REQUEST_CAPACITY_EXHAUSTED`,
383
+ `REQUEST_LEDGER_UNAVAILABLE` (all rejected before any write). CLI errors
384
+ carry the code in `details.requestCode`.
385
+
257
386
  ## Search Commands
258
387
 
259
388
  ### gno search
@@ -734,6 +863,7 @@ Vector index maintenance. Use when `gno similar` returns empty despite embedding
734
863
  ```bash
735
864
  gno vec sync # Fast incremental sync
736
865
  gno vec rebuild # Full rebuild
866
+ gno vec drop <partition> # Drop an abandoned shadow partition (id prefix from gno status)
737
867
  ```
738
868
 
739
869
  | Option | Description |
@@ -362,6 +362,36 @@ gno query "auth" --tags-all security,reviewed
362
362
  gno ask "deployment steps" -c work --tags-any devops --answer
363
363
  ```
364
364
 
365
+ ## Agent Sessions
366
+
367
+ ### Make past agent sessions searchable
368
+
369
+ ```bash
370
+ # Preview local session stores (imports nothing)
371
+ gno sessions discover
372
+
373
+ # Dedicated archive: its own config file + named index
374
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions init --archive ~/gno-sessions/archive --collection sessions-work
375
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions source add claude --harness claude-code --path ~/.claude/projects --collection sessions-work
376
+
377
+ # Dry run, then import; rerun later to pick up new turns
378
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source claude --dry-run
379
+ gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source claude
380
+ ```
381
+
382
+ ### Find a past decision
383
+
384
+ ```bash
385
+ # What the person said, in one project
386
+ gno --config ~/gno-sessions/archive.yml --index sessions search "retry budget" --author human --tags-all project/api
387
+
388
+ # What an agent proposed, in one harness
389
+ gno --config ~/gno-sessions/archive.yml --index sessions search "retry budget" --author assistant --category harness/codex
390
+
391
+ # Read the turn (keep ?index=sessions on the URI)
392
+ gno --config ~/gno-sessions/archive.yml --index sessions get "gno://sessions-work/.gno/records/...?index=sessions"
393
+ ```
394
+
365
395
  ## Tips
366
396
 
367
397
  ### Search Modes
@@ -156,7 +156,8 @@ CLI-only.
156
156
  `GNO_MCP_ENABLE_WRITE=1`. It writes quick notes with structured `source:`
157
157
  frontmatter and returns the same provenance receipt shape as CLI, REST, and SDK
158
158
  capture, plus legacy MCP fields (`docid`, `absPath`, `overwritten`,
159
- `serverInstanceId`).
159
+ `serverInstanceId`). `absPath` is stdio-only: HTTP MCP callers never receive
160
+ host paths and address the note by `uri` + `relPath`.
160
161
 
161
162
  `presetId` accepts `blank`, `project-note`, `research-note`, `decision-note`,
162
163
  `prompt-pattern`, `source-summary`, `idea-original`, `person`,
@@ -195,6 +196,58 @@ transport session, never from tool arguments.
195
196
  rejected (`MEMORY_FENCED_DERIVED`). Optional `source` stores evidence.
196
197
  - Writes sync for FTS before returning and do not auto-embed.
197
198
 
199
+ ## Sessions
200
+
201
+ `gno_sessions_status` (read), `gno_sessions_import` and
202
+ `gno_sessions_automation_run` (write, need `--enable-write`) are in the
203
+ `full` profile only and work on a server started with the session-archive
204
+ pair:
205
+
206
+ ```bash
207
+ gno --config ~/gno-sessions/archive.yml --index sessions mcp --enable-write
208
+ ```
209
+
210
+ - `gno_sessions_status` takes no arguments and lists archive collections,
211
+ registered sources (IDs, availability, unit counts), and the `automation`
212
+ block (daemon state, per-profile state, pending, last run, last success,
213
+ recovery), no host paths.
214
+ - `gno_sessions_automation_run` takes `profileId` only and runs a configured
215
+ profile now; it cannot enable hooks or schedules or add sources. Enabling
216
+ automation is a local owner action (`gno sessions automation enable`).
217
+ - `gno_sessions_import` takes `sourceId` plus optional `dryRun` and `limit`;
218
+ `paths` and other keys are rejected, and there is no MCP discovery. Returns
219
+ the import receipt; `partial` is retried by the next call. It does not
220
+ embed.
221
+ - Search the imported turns with `gno_search` / `gno_query` on the same
222
+ server (filters `author`, `categories`, `tagsAll`); cite by `gno://` URI.
223
+ A human turn is what the person said, an assistant turn a proposal.
224
+ Nothing becomes a `gno_remember` fact unless the user asks.
225
+
226
+ ## Retry-Safe Writes
227
+
228
+ `gno_capture` and `gno_remember` (with `decision`) accept an optional
229
+ `requestId`. Generate one fresh ID (a UUID) per write intent and keep it
230
+ before calling.
231
+
232
+ - After a timeout or lost response, call `gno_request_status` with
233
+ `{ requestId }` before retrying. It is read-only and registered with
234
+ `--enable-write` on the `full` profile (not in `core`).
235
+ - `committed`: use `result` (`uri`, `docid`, `contentHash`); do not resend.
236
+ `pending` or `not_found`: resend the identical call with the same
237
+ `requestId`. `expired`: it already ran; do not resend.
238
+ - An identical retry returns the stored outcome with `request.replayed: true`.
239
+ - Never reuse a `requestId` for a changed payload (`REQUEST_ID_CONFLICT`).
240
+ - `REQUEST_RECOVERY_CONFLICT`, `MEMORY_PREDECESSOR_HASH_MISMATCH`, or
241
+ `MEMORY_SUPERSEDE_CONFLICT`: re-read with `gno_get` / `gno_recall` and
242
+ decide again; never force-overwrite. `REQUEST_PENDING`: retry the same ID
243
+ later.
244
+ - `requestId` is not the recall `receipt`: the receipt fences recalled text;
245
+ the ID identifies one write.
246
+ - Over HTTP MCP, request IDs belong to the authorized identity (loopback or
247
+ bearer token). Rotating the token starts a new namespace: an old ID reads
248
+ `not_found`, so do not blindly resend an uncertain old write as new.
249
+ - Errors arrive as tool text `CODE: message` with `structuredContent.error`.
250
+
198
251
  ## Uninstall
199
252
 
200
253
  ```bash
@@ -18,6 +18,12 @@ gno capture "summary or fact" --preset decision-note --title "<title>" --json
18
18
  gno capture --file ./clip.md --source-url https://example.com --source-kind web --json
19
19
  ```
20
20
 
21
+ When a retry may follow a timeout or lost response, pass
22
+ `--request-id <uuid>` (one fresh ID per note). Check
23
+ `gno request-status <uuid>` before retrying: `committed` = already saved,
24
+ do not resend; `pending` or `not_found` = resend the identical command with
25
+ the same ID. Never reuse the ID for changed content.
26
+
21
27
  2. For an explicit browser capture, use the local Chromium clipper. The user
22
28
  selects visible top-frame text or chooses Reader mode, reviews the
23
29
  server-owned preview, then confirms the write. Pairing and capture stay
@@ -42,6 +42,12 @@ gno remember "<fact>" --scope <scope> --add \
42
42
  --source "<where this came from>" --receipt /tmp/recall.json --json
43
43
  ```
44
44
 
45
+ To make a retry safe, add `--request-id <uuid>` (one fresh ID per fact,
46
+ saved before sending). If the response is lost, run
47
+ `gno request-status <uuid>` first: `committed` means do not resend;
48
+ `pending` or `not_found` means resend the identical command with the same
49
+ ID.
50
+
45
51
  4. Read the result. `outcome: "added"` plus `sync.status: "completed"` means
46
52
  the fact file exists and is retrievable now; a `failed` sync means the
47
53
  file exists and the index lags (`gno update <collection>`).
@@ -35,6 +35,11 @@ gno remember "<replacement text>" --scope <scope> \
35
35
  The scriptable spelling `--decision supersede --predecessor <uri>` means
36
36
  the same thing.
37
37
 
38
+ Add `--request-id <uuid>` so a lost response can be retried without a double
39
+ supersede: check `gno request-status <uuid>` first, and resend only the
40
+ identical command with the same ID when it reports `pending` or `not_found`.
41
+ The request ID is separate from `--receipt`.
42
+
38
43
  4. Read the result. `outcome: "superseded"` returns the successor record with
39
44
  `supersedes: [<uri>]`.
40
45
  - `MEMORY_PREDECESSOR_HASH_MISMATCH`: the fact changed since the recall.