@gmickel/gno 1.31.0 → 1.33.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 (77) hide show
  1. package/README.md +15 -5
  2. package/assets/skill/SKILL.md +34 -0
  3. package/assets/skill/cli-reference.md +10 -2
  4. package/browser-extension/artifacts/{gno-browser-clipper-v1.31.0.zip → gno-browser-clipper-v1.33.0.zip} +0 -0
  5. package/browser-extension/artifacts/gno-browser-clipper-v1.33.0.zip.sha256 +1 -0
  6. package/browser-extension/dist/manifest.json +1 -1
  7. package/package.json +5 -1
  8. package/spec/cli.md +35 -1
  9. package/spec/db/schema.sql +55 -0
  10. package/spec/mcp.md +114 -11
  11. package/spec/output-schemas/file-refactor-apply-result.schema.json +305 -0
  12. package/spec/output-schemas/file-refactor-preview.schema.json +393 -0
  13. package/spec/output-schemas/publish-artifact.schema.json +76 -1
  14. package/src/cli/commands/publish.ts +43 -7
  15. package/src/core/document-capabilities.ts +13 -0
  16. package/src/core/file-ops.ts +129 -1
  17. package/src/core/file-refactor-adapter.ts +329 -0
  18. package/src/core/file-refactor-apply-edits.ts +61 -0
  19. package/src/core/file-refactor-apply-fs.ts +512 -0
  20. package/src/core/file-refactor-apply-safety.ts +340 -0
  21. package/src/core/file-refactor-apply-validate.ts +401 -0
  22. package/src/core/file-refactor-contract.ts +486 -0
  23. package/src/core/file-refactor-destination.ts +123 -0
  24. package/src/core/file-refactor-from-snapshot.ts +148 -0
  25. package/src/core/file-refactor-journal-port.ts +150 -0
  26. package/src/core/file-refactor-journal.ts +347 -0
  27. package/src/core/file-refactor-paths.ts +60 -0
  28. package/src/core/file-refactor-plan-classify.ts +208 -0
  29. package/src/core/file-refactor-plan-validate.ts +169 -0
  30. package/src/core/file-refactor-planner-types.ts +62 -0
  31. package/src/core/file-refactor-planner.ts +423 -0
  32. package/src/core/file-refactor-resolve.ts +280 -0
  33. package/src/core/file-refactor-service.ts +468 -0
  34. package/src/core/file-refactors.ts +84 -56
  35. package/src/core/link-destination-parse.ts +275 -0
  36. package/src/core/link-inventory-markdown.ts +454 -0
  37. package/src/core/link-inventory-opaque.ts +244 -0
  38. package/src/core/link-inventory-types.ts +47 -0
  39. package/src/core/link-inventory.ts +182 -0
  40. package/src/core/link-relevance.ts +150 -0
  41. package/src/ingestion/strip.ts +152 -26
  42. package/src/mcp/tools/index.ts +18 -17
  43. package/src/mcp/tools/workspace-write.ts +215 -97
  44. package/src/publish/artifact-asset-codec.ts +75 -0
  45. package/src/publish/artifact-asset-contract.ts +152 -0
  46. package/src/publish/artifact-asset-parse.ts +401 -0
  47. package/src/publish/artifact-asset-sniff.ts +108 -0
  48. package/src/publish/artifact-asset-validate.ts +209 -0
  49. package/src/publish/artifact-assets.ts +58 -0
  50. package/src/publish/artifact-validation.ts +32 -6
  51. package/src/publish/artifact.ts +50 -3
  52. package/src/publish/attachment-bundle.ts +145 -0
  53. package/src/publish/attachment-discover.ts +203 -0
  54. package/src/publish/attachment-load.ts +133 -0
  55. package/src/publish/attachment-obsidian.ts +45 -0
  56. package/src/publish/attachment-path.ts +334 -0
  57. package/src/publish/attachment-raster.ts +852 -0
  58. package/src/publish/attachment-resolver.ts +280 -0
  59. package/src/publish/attachment-types.ts +54 -0
  60. package/src/publish/encrypted-export.ts +121 -44
  61. package/src/publish/export-attachments.ts +224 -0
  62. package/src/publish/export-service.ts +142 -80
  63. package/src/publish/obsidian-sanitize.ts +121 -13
  64. package/src/sdk/client.ts +167 -115
  65. package/src/sdk/index.ts +7 -0
  66. package/src/sdk/types.ts +32 -2
  67. package/src/serve/file-refactor-http.ts +239 -0
  68. package/src/serve/public/components/RefactorImpactPreview.tsx +227 -0
  69. package/src/serve/public/globals.built.css +1 -1
  70. package/src/serve/public/pages/DocView.tsx +176 -41
  71. package/src/serve/routes/api.ts +193 -105
  72. package/src/store/migrations/026-file-refactor-recovery-journal.ts +72 -0
  73. package/src/store/migrations/index.ts +2 -0
  74. package/src/store/sqlite/adapter.ts +452 -0
  75. package/src/store/sqlite/file-refactor-journal-store.ts +275 -0
  76. package/src/store/types.ts +84 -0
  77. package/browser-extension/artifacts/gno-browser-clipper-v1.31.0.zip.sha256 +0 -1
package/README.md CHANGED
@@ -117,7 +117,7 @@ gno daemon --detach # headless indexing + resident MCP gateway
117
117
 
118
118
  <!-- public-truth:current-version -->
119
119
 
120
- > Current release: **v1.31.0** — see [CHANGELOG.md](./CHANGELOG.md)
120
+ > Current release: **v1.33.0** — see [CHANGELOG.md](./CHANGELOG.md)
121
121
 
122
122
  <!-- /public-truth -->
123
123
 
@@ -694,7 +694,7 @@ Open `http://localhost:3000` to:
694
694
  configured MCP retrieval without changing client config. Skill installation
695
695
  is visible, but client runtime execution cannot be proven automatically
696
696
  - **Manage files safely**: Rename, reveal, or move editable files to Trash with explicit index-vs-disk semantics
697
- - **Refactor files safely**: Move, duplicate, and organize editable notes with reference warnings
697
+ - **Refactor files safely**: Preview and atomically rename or move editable notes while GNO rewrites supported wiki and Markdown references; stale or unsafe plans fail closed
698
698
  - **Switch presets**: Change models live without restart
699
699
  - **Command palette**: Jump, create, refactor, and section-navigate from one keyboard-first surface
700
700
 
@@ -773,7 +773,7 @@ GNO is local-first, but sometimes you want a URL to send someone. [**gno.sh**](h
773
773
 
774
774
  ![gno.sh publish reader](./assets/screenshots/publish-reader.jpg)
775
775
 
776
- The workflow is deliberately explicit: **export locally → upload artifact → share URL**. Private and `publish: false` notes stay on your machine. Exported artifacts omit local collection paths and source URIs.
776
+ The workflow is deliberately explicit: **export locally → upload artifact → share URL**. Private and `publish: false` notes stay on your machine. Exported artifacts omit local collection paths and source URIs. Local PNG/JPEG/GIF/WebP/AVIF images (Markdown and Obsidian embeds) are bundled into the artifact with SHA-256 dedup, `gno-asset:` sentinels, and an exact 100 MiB serialized ceiling; external HTTPS images stay as URLs. Encrypted shares keep image bytes inside ciphertext only. Invite-only note text publishes today, but invite-only image delivery on gno.sh is not supported yet.
777
777
 
778
778
  ```bash
779
779
  # Export a single note
@@ -817,6 +817,15 @@ agent capabilities or manifests. Encrypted exports remain ciphertext-only.
817
817
  Reader metadata drops embedded local path or GNO/file URI tokens; canonical
818
818
  and image fields accept only uncredentialed public HTTP(S) targets.
819
819
 
820
+ Resolved local PNG, JPEG, GIF, WebP, and AVIF references are bundled,
821
+ content-addressed, and deduplicated; external public HTTPS images remain
822
+ external. The exact serialized artifact is capped at 100 MiB. Public images
823
+ use immutable snapshot/generation URLs, secret-link images are authorized on
824
+ every request, and encrypted image bytes exist only inside ciphertext before
825
+ the browser creates scoped Blob URLs. Invite-only bundled-image delivery is
826
+ currently fail-closed; use an asset-free invite, secret link, or encrypted
827
+ share when local images are required.
828
+
820
829
  Republishing a public, secret-link, or invite-only artifact updates the same URL. Encrypted shares should be replaced from a fresh local export so the server never needs your plaintext.
821
830
 
822
831
  Encrypted source-backed publish on `gno.sh` is intentionally disabled. For encrypted shares, use:
@@ -863,9 +872,10 @@ curl http://localhost:3000/api/health
863
872
  | `/api/docs` | GET | List documents |
864
873
  | `/api/docs` | POST | Create document |
865
874
  | `/api/docs/:id` | PUT | Update document content |
866
- | `/api/docs/:id/move` | POST | Move editable document |
875
+ | `/api/docs/:id/rename` | POST | Apply confirmed safe rename |
876
+ | `/api/docs/:id/move` | POST | Apply confirmed safe move |
867
877
  | `/api/docs/:id/duplicate` | POST | Duplicate editable document |
868
- | `/api/docs/:id/refactor-plan` | POST | Preview file-op warnings |
878
+ | `/api/docs/:id/refactor-plan` | POST | Preview reference-safe plan |
869
879
  | `/api/docs/:id/deactivate` | POST | Remove from index |
870
880
  | `/api/doc` | GET | Get document content |
871
881
  | `/api/doc/:id/sections` | GET | Get document sections |
@@ -92,6 +92,17 @@ Recipe rules:
92
92
  | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
93
93
  | **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics |
94
94
 
95
+ ### Publishing with local images
96
+
97
+ `gno publish export` bundles resolved local PNG, JPEG, GIF, WebP, and AVIF
98
+ references, deduplicates identical bytes, preserves public HTTPS images, and
99
+ enforces the 100 MiB exact serialized artifact limit. Review `assetSummary`
100
+ in `--json` output for unresolved or unsupported references. Public and
101
+ secret-link readers serve authorized hosted URLs; encrypted exports keep image
102
+ bytes inside ciphertext and create scoped Blob URLs only after browser
103
+ decryption. Hosted invite-only bundled-image delivery is currently
104
+ fail-closed, so use an asset-free invite, secret link, or encrypted share.
105
+
95
106
  ## Search Modes
96
107
 
97
108
  | Command | Speed | Best For |
@@ -499,6 +510,29 @@ search must include the new note. Browser provenance fields are
499
510
  `extractionHash`, `finalBodyHash`, `clipIdentity`, and `previewDigest`—do not
500
511
  invent `sourceHash`.
501
512
 
513
+ ## Reference-Safe Rename and Move
514
+
515
+ When MCP writes are enabled and the user asks to rename or move an editable
516
+ note, always use the operation-specific two-step tool. Never invent a digest or
517
+ collapse preview and apply into one call.
518
+
519
+ 1. Call `gno_rename_note` or `gno_move_note` with `action: "preview"` and the
520
+ exact source/destination.
521
+ 2. Inspect `canApply`, `safety.blockingReasons`, and `examinedReferences`.
522
+ Stop and report ambiguous, malformed, unsupported, read-only, occupied,
523
+ cross-collection, or truncated plans.
524
+ 3. Only after explicit user approval, call the same tool with `action: "apply"`,
525
+ the preview's exact `schemaVersion` and `planDigest`, `confirmation: "apply"`,
526
+ and `confirm: true`.
527
+ 4. Treat `applied_with_sync_pending` as a committed filesystem refactor whose
528
+ index still needs `gno_sync` or `gno_index`; do not retry the file mutation.
529
+ For `stale_plan`, preview again instead of reusing the old digest.
530
+
531
+ Supported wiki and Markdown destinations are rewritten in the same
532
+ all-or-rollback filesystem transaction as the source move. Duplicate and
533
+ create-folder do not retarget inbound references. Authentication alone never
534
+ enables these MCP writes.
535
+
502
536
  ## Collection-specific embedding models
503
537
 
504
538
  Collections can override the global embedding model with `models.embed`.
@@ -887,11 +887,19 @@ export pipeline runs a sanitizer over each note's markdown. It:
887
887
  `_internal/` convention is treated as never-publish)
888
888
  - converts `[[Target|Alias]]` to the alias text, and `[[Target]]` to the
889
889
  tail segment of the target
890
- - drops `![[image.png]]` embeds (attachments are not bundled yet) with a
891
- warning so the author can migrate to `![alt](url)` or wait for bundling
890
+ - resolves local `![[image.png]]` / Markdown image refs for PNG/JPEG/GIF/WebP/
891
+ AVIF (AVIF must be AV1-decodable at producer ingress) into content-addressed
892
+ `gno-asset:<sha256>` sentinels (deduped; exact 100 MiB serialized ceiling;
893
+ ciphertext field bounds align to that envelope); preserves external HTTPS
894
+ images; skips fenced code (backtick and tilde); drops unsupported/missing/
895
+ unsafe refs with diagnostics
892
896
  - refuses to export a note whose frontmatter contains `publish: false`
893
897
  (single-note export errors; collection export silently skips)
894
898
 
899
+ Successful exports include `assetSummary` in `--json`. Encrypted visibility
900
+ keeps raster bytes inside ciphertext only. Hosted invite-only image delivery
901
+ is currently fail-closed on gno.sh.
902
+
895
903
  Every sanitizer decision surfaces in the CLI output as a "Preprocessor
896
904
  notes" section, on the `--json` response under `warnings`, and on
897
905
  `--preview` as a structured report — so nothing is silently lost.
@@ -0,0 +1 @@
1
+ c398c09680951afa0b5d436f3b92cf3dfb6e49427b9df83830ce899d3b03d7e4 gno-browser-clipper-v1.33.0.zip
@@ -21,5 +21,5 @@
21
21
  "content_security_policy": {
22
22
  "extension_pages": "script-src 'self'; object-src 'none'; connect-src http://127.0.0.1:*"
23
23
  },
24
- "version": "1.31.0"
24
+ "version": "1.33.0"
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "1.31.0",
3
+ "version": "1.33.0",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
6
  "embeddings",
@@ -178,6 +178,9 @@
178
178
  "jsonc-parser": "3.3.1",
179
179
  "lucide-react": "1.28.0",
180
180
  "markitdown-ts": "0.0.10",
181
+ "mdast-util-from-markdown": "2.0.3",
182
+ "mdast-util-gfm": "3.1.0",
183
+ "micromark-extension-gfm": "3.0.0",
181
184
  "minimatch": "10.2.6",
182
185
  "nanoid": "6.0.0",
183
186
  "node-llama-cpp": "3.19.1",
@@ -190,6 +193,7 @@
190
193
  "react-markdown": "10.1.0",
191
194
  "rehype-sanitize": "6.0.0",
192
195
  "remark-gfm": "4.0.1",
196
+ "sharp": "0.35.3",
193
197
  "shiki": "4.3.1",
194
198
  "sqlite-vec": "0.1.9",
195
199
  "streamdown": "2.5.0",
package/spec/cli.md CHANGED
@@ -1949,6 +1949,19 @@ tokens MUST be filtered. Canonical and image metadata MUST contain
1949
1949
  uncredentialed public HTTP(S) targets; local hostnames and literal loopback,
1950
1950
  private, or link-local addresses MUST be filtered.
1951
1951
 
1952
+ When local raster attachments are bundled, the V1 artifact MAY include
1953
+ `assets[]` and `requiredCapabilities: ["bundled-raster-assets@1"]`. Export
1954
+ success payloads (CLI `--json` and `POST /api/publish/export`) MUST include a
1955
+ deterministic `assetSummary` with asset/ref counts, raw/encoded/final UTF-8
1956
+ upload bytes, dedup savings, external image count, and unresolved/unsupported
1957
+ diagnostics. Exact final serialized upload bytes MUST be enforced against the
1958
+ 100 MiB ceiling before returning. Encrypted V2 ciphertext string bounds MUST
1959
+ align to that same 100 MiB final-envelope budget and MUST NOT replace exact
1960
+ final serialized measurement as the authoritative upload gate. Producer
1961
+ ingress MUST require AV1-decodable AVIF payloads (structural BMFF alone is
1962
+ insufficient). Asset-free exports omit `assets` /
1963
+ `requiredCapabilities` and report zero asset counts.
1964
+
1952
1965
  Secret-link and invite-only V1 spaces MUST NOT contain a manifest or agent
1953
1966
  capability field. Encrypted V2 spaces MUST contain only ciphertext parameters,
1954
1967
  the opaque secret token, route slug, source type, and encrypted visibility; no
@@ -1956,7 +1969,9 @@ plaintext manifest or evidence may appear outside the ciphertext. V2 builders
1956
1969
  MUST emit a closed projection, validate payload strings as non-empty bounded
1957
1970
  base64, require a positive safe-integer KDF iteration count, and bound the
1958
1971
  non-blank opaque token. Caller-supplied extension fields MUST NOT enter the
1959
- artifact.
1972
+ artifact. Encrypted export MUST place bundled assets only inside the encrypted
1973
+ client payload. The outer V2 envelope MUST contain neither plaintext note
1974
+ content, asset descriptors, source references, nor raster bytes.
1960
1975
 
1961
1976
  ---
1962
1977
 
@@ -3448,6 +3463,25 @@ Error codes match exit codes: `VALIDATION` (exit 1), `RUNTIME` (exit 2), `NOT_RU
3448
3463
 
3449
3464
  ---
3450
3465
 
3466
+ ## Workspace file refactors (non-CLI)
3467
+
3468
+ Reference-safe note rename and same-collection move use a transport-neutral
3469
+ preview/apply contract defined in `src/core/file-refactors.ts` and frozen as:
3470
+
3471
+ - `gno://schemas/file-refactor-preview@1.0`
3472
+ - `gno://schemas/file-refactor-apply-result@1.0`
3473
+
3474
+ Surfaces that adapt the contract are REST/Web UI, SDK, and write-gated MCP
3475
+ (`gno_rename_note`, `gno_move_note`). This specification intentionally does
3476
+ **not** add a CLI command family or generic action bus for refactors.
3477
+ Duplicate-note and create-folder keep their existing shipped semantics and do
3478
+ not retarget inbound references.
3479
+
3480
+ The contract separates durable filesystem commit/rollback from post-commit
3481
+ index convergence. A successful filesystem refactor is never rolled back solely
3482
+ because reindexing is temporarily unavailable
3483
+ (`applied_with_sync_pending`).
3484
+
3451
3485
  ## See Also
3452
3486
 
3453
3487
  - [MCP Specification](./mcp.md)
@@ -21,6 +21,7 @@
21
21
  -- retrieval_trace_exports/export_traces - Export manifests and trace joins
22
22
  -- document_changes - Bounded metadata-only document lifecycle journal
23
23
  -- document_change_journal_state - Monotonic cursor/retention boundary
24
+ -- file_refactor_recovery_journal - Content-free rename/move recovery receipts
24
25
 
25
26
  -- ─────────────────────────────────────────────────────────────────────────────
26
27
  -- Schema Metadata
@@ -742,3 +743,57 @@ CREATE TABLE IF NOT EXISTS clipper_capture_idempotency (
742
743
 
743
744
  CREATE INDEX IF NOT EXISTS idx_clipper_idempotency_created
744
745
  ON clipper_capture_idempotency(created_at_ms, grant_id, key_hash);
746
+
747
+ -- ─────────────────────────────────────────────────────────────────────────────
748
+ -- File refactor recovery journal (content-free)
749
+ -- ─────────────────────────────────────────────────────────────────────────────
750
+
751
+ -- Durable receipts for multi-file rename/move apply. Stores IDs, digests,
752
+ -- collection/relpaths, phase/state, timestamps, and fingerprints/status only.
753
+ -- Never stores note bodies or replacement content.
754
+ -- Bounded: create prunes oldest terminal receipts (converged/rolled_back/aborted)
755
+ -- under FILE_REFACTOR_JOURNAL_MAX_RECEIPTS; never prunes recovery_required.
756
+
757
+ CREATE TABLE IF NOT EXISTS file_refactor_recovery_journal (
758
+ journal_id TEXT PRIMARY KEY,
759
+ plan_digest TEXT NOT NULL,
760
+ collection TEXT NOT NULL,
761
+ operation TEXT NOT NULL
762
+ CHECK (operation IN ('rename', 'move')),
763
+ source_rel_path TEXT NOT NULL,
764
+ target_rel_path TEXT NOT NULL,
765
+ phase TEXT NOT NULL
766
+ CHECK (phase IN (
767
+ 'prepared', 'staging', 'committing', 'committed', 'sync_pending',
768
+ 'converged', 'rolling_back', 'rolled_back', 'recovery_required',
769
+ 'aborted'
770
+ )),
771
+ phase_ordinal INTEGER NOT NULL CHECK (phase_ordinal >= 0),
772
+ filesystem_state TEXT NOT NULL
773
+ CHECK (filesystem_state IN (
774
+ 'unchanged', 'committed', 'rolled_back', 'recovery_required'
775
+ )),
776
+ index_state TEXT NOT NULL
777
+ CHECK (index_state IN (
778
+ 'not_attempted', 'pending', 'converged', 'skipped'
779
+ )),
780
+ file_entries_json TEXT NOT NULL
781
+ CHECK (length(CAST(file_entries_json AS BLOB)) <= 65536),
782
+ created_at_ms INTEGER NOT NULL CHECK (created_at_ms >= 0),
783
+ updated_at_ms INTEGER NOT NULL CHECK (updated_at_ms >= 0),
784
+ CHECK (length(CAST(journal_id AS BLOB)) BETWEEN 1 AND 128),
785
+ CHECK (
786
+ length(plan_digest) = 64
787
+ AND plan_digest NOT GLOB '*[^0-9a-f]*'
788
+ ),
789
+ CHECK (length(CAST(collection AS BLOB)) BETWEEN 1 AND 256),
790
+ CHECK (length(CAST(source_rel_path AS BLOB)) BETWEEN 1 AND 4096),
791
+ CHECK (length(CAST(target_rel_path AS BLOB)) BETWEEN 1 AND 4096),
792
+ CHECK (updated_at_ms >= created_at_ms)
793
+ );
794
+
795
+ CREATE INDEX IF NOT EXISTS idx_file_refactor_journal_plan_digest
796
+ ON file_refactor_recovery_journal(plan_digest, updated_at_ms DESC, journal_id DESC);
797
+
798
+ CREATE INDEX IF NOT EXISTS idx_file_refactor_journal_collection
799
+ ON file_refactor_recovery_journal(collection, updated_at_ms DESC);
package/spec/mcp.md CHANGED
@@ -1798,39 +1798,140 @@ Create a folder inside an existing collection (write-enabled).
1798
1798
 
1799
1799
  Rename an editable note in place (write-enabled).
1800
1800
 
1801
+ Same-collection rename is covered by the transport-neutral reference-safe
1802
+ refactor contract (`src/core/file-refactors.ts`). Preview and apply share one
1803
+ versioned schema pair across MCP, REST/SDK, and UI adapters:
1804
+
1805
+ - Preview plan: `gno://schemas/file-refactor-preview@1.0`
1806
+ - Apply result: `gno://schemas/file-refactor-apply-result@1.0`
1807
+
1808
+ The preview enumerates examined wiki/Markdown references with classifications
1809
+ and stable reason codes, destination-only edit spans, precondition fingerprints,
1810
+ a deterministic `planDigest`, safety summary, and `canApply`. Apply requires the
1811
+ exact `planDigest`, confirmation token `apply`, `confirm: true`, and
1812
+ `schemaVersion: "1.0"`. Apply never silently preview-and-confirms. Terminal
1813
+ statuses are `applied`, `applied_with_sync_pending`, `conflict`, `stale_plan`,
1814
+ `unsupported`, and `failed_rolled_back`.
1815
+
1816
+ Filesystem commit (moved note + accepted reference rewrites) is an atomic
1817
+ all-or-rollback boundary. Index/link convergence runs only after a durable
1818
+ filesystem commit and is **not** the same transaction; reindex failure returns
1819
+ `applied_with_sync_pending` without rolling back committed files.
1820
+
1821
+ MCP annotations remain hints, not authorization. Write gating (`--enable-write`)
1822
+ and destructive confirmation (`confirm: true` + `confirmation: "apply"`) still
1823
+ apply. No generic action-bus tool is introduced.
1824
+
1801
1825
  **Input Schema:**
1802
1826
 
1803
1827
  ```json
1804
1828
  {
1805
1829
  "type": "object",
1806
- "properties": {
1807
- "ref": { "type": "string" },
1808
- "name": { "type": "string" }
1809
- },
1810
- "required": ["ref", "name"]
1830
+ "oneOf": [
1831
+ {
1832
+ "properties": {
1833
+ "action": { "const": "preview" },
1834
+ "ref": { "type": "string" },
1835
+ "name": { "type": "string" }
1836
+ },
1837
+ "required": ["action", "ref", "name"],
1838
+ "additionalProperties": false
1839
+ },
1840
+ {
1841
+ "properties": {
1842
+ "action": { "const": "apply" },
1843
+ "ref": { "type": "string" },
1844
+ "name": { "type": "string" },
1845
+ "schemaVersion": { "const": "1.0" },
1846
+ "planDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
1847
+ "confirmation": { "const": "apply" },
1848
+ "confirm": { "const": true }
1849
+ },
1850
+ "required": [
1851
+ "action",
1852
+ "ref",
1853
+ "name",
1854
+ "schemaVersion",
1855
+ "planDigest",
1856
+ "confirmation",
1857
+ "confirm"
1858
+ ],
1859
+ "additionalProperties": false
1860
+ }
1861
+ ]
1811
1862
  }
1812
1863
  ```
1813
1864
 
1865
+ **Output Schema:**
1866
+
1867
+ - `action=preview` → `gno://schemas/file-refactor-preview@1.0` (content-free plan)
1868
+ - `action=apply` → `gno://schemas/file-refactor-apply-result@1.0` (content-free receipt)
1869
+
1870
+ Missing or incorrect apply confirmation fails before mutation.
1871
+
1814
1872
  ---
1815
1873
 
1816
1874
  ### gno_move_note
1817
1875
 
1818
1876
  Move an editable note to another folder in the same collection (write-enabled).
1819
1877
 
1878
+ Cross-collection moves are out of scope and fail closed with
1879
+ `cross_collection_unsupported`. Preview/apply semantics, destination-only edit
1880
+ spans, stale-plan protection, and the filesystem-vs-index mutation boundary match
1881
+ `gno_rename_note` and use the same schemas:
1882
+
1883
+ - Preview plan: `gno://schemas/file-refactor-preview@1.0`
1884
+ - Apply result: `gno://schemas/file-refactor-apply-result@1.0`
1885
+
1820
1886
  **Input Schema:**
1821
1887
 
1822
1888
  ```json
1823
1889
  {
1824
1890
  "type": "object",
1825
- "properties": {
1826
- "ref": { "type": "string" },
1827
- "folderPath": { "type": "string" },
1828
- "name": { "type": "string" }
1829
- },
1830
- "required": ["ref", "folderPath"]
1891
+ "oneOf": [
1892
+ {
1893
+ "properties": {
1894
+ "action": { "const": "preview" },
1895
+ "ref": { "type": "string" },
1896
+ "folderPath": { "type": "string" },
1897
+ "name": { "type": "string" }
1898
+ },
1899
+ "required": ["action", "ref", "folderPath"],
1900
+ "additionalProperties": false
1901
+ },
1902
+ {
1903
+ "properties": {
1904
+ "action": { "const": "apply" },
1905
+ "ref": { "type": "string" },
1906
+ "folderPath": { "type": "string" },
1907
+ "name": { "type": "string" },
1908
+ "schemaVersion": { "const": "1.0" },
1909
+ "planDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
1910
+ "confirmation": { "const": "apply" },
1911
+ "confirm": { "const": true }
1912
+ },
1913
+ "required": [
1914
+ "action",
1915
+ "ref",
1916
+ "folderPath",
1917
+ "schemaVersion",
1918
+ "planDigest",
1919
+ "confirmation",
1920
+ "confirm"
1921
+ ],
1922
+ "additionalProperties": false
1923
+ }
1924
+ ]
1831
1925
  }
1832
1926
  ```
1833
1927
 
1928
+ **Output Schema:**
1929
+
1930
+ - `action=preview` → `gno://schemas/file-refactor-preview@1.0` (content-free plan)
1931
+ - `action=apply` → `gno://schemas/file-refactor-apply-result@1.0` (content-free receipt)
1932
+
1933
+ Missing or incorrect apply confirmation fails before mutation.
1934
+
1834
1935
  ---
1835
1936
 
1836
1937
  ### gno_duplicate_note
@@ -2243,6 +2344,8 @@ Output schemas include version in `$id`:
2243
2344
 
2244
2345
  - `gno://schemas/search-result@1.0`
2245
2346
  - `gno://schemas/capture-receipt@1.0`
2347
+ - `gno://schemas/file-refactor-preview@1.0`
2348
+ - `gno://schemas/file-refactor-apply-result@1.0`
2246
2349
 
2247
2350
  Clients should check schema version for compatibility.
2248
2351