ctxr-cli 0.8.0 → 0.10.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 (250) hide show
  1. package/README.md +313 -22
  2. package/dist/adapters/types.d.ts +0 -5
  3. package/dist/adapters/types.d.ts.map +1 -1
  4. package/dist/commands/adapters-generate.d.ts.map +1 -1
  5. package/dist/commands/adapters-generate.js +2 -3
  6. package/dist/commands/adapters-generate.js.map +1 -1
  7. package/dist/commands/context-gather.d.ts +22 -0
  8. package/dist/commands/context-gather.d.ts.map +1 -0
  9. package/dist/commands/context-gather.js +36 -0
  10. package/dist/commands/context-gather.js.map +1 -0
  11. package/dist/commands/graph-query.d.ts.map +1 -1
  12. package/dist/commands/graph-query.js +6 -8
  13. package/dist/commands/graph-query.js.map +1 -1
  14. package/dist/commands/ingest.d.ts +22 -9
  15. package/dist/commands/ingest.d.ts.map +1 -1
  16. package/dist/commands/ingest.js +86 -24
  17. package/dist/commands/ingest.js.map +1 -1
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +22 -5
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/publish-check.d.ts.map +1 -1
  22. package/dist/commands/publish-check.js +8 -0
  23. package/dist/commands/publish-check.js.map +1 -1
  24. package/dist/commands/publish-new.d.ts.map +1 -1
  25. package/dist/commands/publish-new.js +15 -0
  26. package/dist/commands/publish-new.js.map +1 -1
  27. package/dist/commands/serve.d.ts.map +1 -1
  28. package/dist/commands/serve.js +33 -11
  29. package/dist/commands/serve.js.map +1 -1
  30. package/dist/commands/session-start.d.ts.map +1 -1
  31. package/dist/commands/session-start.js +9 -1
  32. package/dist/commands/session-start.js.map +1 -1
  33. package/dist/commands/source-check.d.ts.map +1 -1
  34. package/dist/commands/source-check.js +52 -9
  35. package/dist/commands/source-check.js.map +1 -1
  36. package/dist/commands/source-stamp.d.ts +6 -5
  37. package/dist/commands/source-stamp.d.ts.map +1 -1
  38. package/dist/commands/source-stamp.js +8 -7
  39. package/dist/commands/source-stamp.js.map +1 -1
  40. package/dist/commands/update.d.ts.map +1 -1
  41. package/dist/commands/update.js +7 -1
  42. package/dist/commands/update.js.map +1 -1
  43. package/dist/commands/verify.d.ts +11 -2
  44. package/dist/commands/verify.d.ts.map +1 -1
  45. package/dist/commands/verify.js +86 -5
  46. package/dist/commands/verify.js.map +1 -1
  47. package/dist/commands/version.d.ts +31 -0
  48. package/dist/commands/version.d.ts.map +1 -0
  49. package/dist/commands/version.js +87 -0
  50. package/dist/commands/version.js.map +1 -0
  51. package/dist/config/defaults.d.ts +113 -4
  52. package/dist/config/defaults.d.ts.map +1 -1
  53. package/dist/config/defaults.js +83 -4
  54. package/dist/config/defaults.js.map +1 -1
  55. package/dist/config/load.d.ts +2 -2
  56. package/dist/config/load.d.ts.map +1 -1
  57. package/dist/config/load.js +13 -3
  58. package/dist/config/load.js.map +1 -1
  59. package/dist/config/render.d.ts +5 -0
  60. package/dist/config/render.d.ts.map +1 -1
  61. package/dist/config/render.js +62 -3
  62. package/dist/config/render.js.map +1 -1
  63. package/dist/config/schema.d.ts +47 -76
  64. package/dist/config/schema.d.ts.map +1 -1
  65. package/dist/config/schema.js +171 -134
  66. package/dist/config/schema.js.map +1 -1
  67. package/dist/core/agents-doc.d.ts.map +1 -1
  68. package/dist/core/agents-doc.js +4 -1
  69. package/dist/core/agents-doc.js.map +1 -1
  70. package/dist/core/browse/nav.d.ts.map +1 -1
  71. package/dist/core/browse/nav.js +4 -1
  72. package/dist/core/browse/nav.js.map +1 -1
  73. package/dist/core/browse/preferences.d.ts +26 -0
  74. package/dist/core/browse/preferences.d.ts.map +1 -0
  75. package/dist/core/browse/preferences.js +74 -0
  76. package/dist/core/browse/preferences.js.map +1 -0
  77. package/dist/core/browse/routes.d.ts +10 -8
  78. package/dist/core/browse/routes.d.ts.map +1 -1
  79. package/dist/core/browse/routes.js +113 -24
  80. package/dist/core/browse/routes.js.map +1 -1
  81. package/dist/core/browse/templates.d.ts +14 -4
  82. package/dist/core/browse/templates.d.ts.map +1 -1
  83. package/dist/core/browse/templates.js +22 -4
  84. package/dist/core/browse/templates.js.map +1 -1
  85. package/dist/core/checks/harness-portability-checks.d.ts +22 -1
  86. package/dist/core/checks/harness-portability-checks.d.ts.map +1 -1
  87. package/dist/core/checks/harness-portability-checks.js +48 -4
  88. package/dist/core/checks/harness-portability-checks.js.map +1 -1
  89. package/dist/core/checks/integrity-checks.d.ts +0 -2
  90. package/dist/core/checks/integrity-checks.d.ts.map +1 -1
  91. package/dist/core/checks/integrity-checks.js +2 -27
  92. package/dist/core/checks/integrity-checks.js.map +1 -1
  93. package/dist/core/checks/manifest.d.ts.map +1 -1
  94. package/dist/core/checks/manifest.js +2 -0
  95. package/dist/core/checks/manifest.js.map +1 -1
  96. package/dist/core/checks/organize-checks.d.ts +11 -1
  97. package/dist/core/checks/organize-checks.d.ts.map +1 -1
  98. package/dist/core/checks/organize-checks.js +42 -12
  99. package/dist/core/checks/organize-checks.js.map +1 -1
  100. package/dist/core/checks/retrieval-checks.d.ts +9 -0
  101. package/dist/core/checks/retrieval-checks.d.ts.map +1 -0
  102. package/dist/core/checks/retrieval-checks.js +30 -0
  103. package/dist/core/checks/retrieval-checks.js.map +1 -0
  104. package/dist/core/command.d.ts +6 -0
  105. package/dist/core/command.d.ts.map +1 -1
  106. package/dist/core/content/canonicalize.d.ts +10 -0
  107. package/dist/core/content/canonicalize.d.ts.map +1 -1
  108. package/dist/core/content/canonicalize.js +12 -0
  109. package/dist/core/content/canonicalize.js.map +1 -1
  110. package/dist/core/env.d.ts +5 -0
  111. package/dist/core/env.d.ts.map +1 -1
  112. package/dist/core/env.js +3 -0
  113. package/dist/core/env.js.map +1 -1
  114. package/dist/core/environment/probe.d.ts +12 -0
  115. package/dist/core/environment/probe.d.ts.map +1 -0
  116. package/dist/core/environment/probe.js +36 -0
  117. package/dist/core/environment/probe.js.map +1 -0
  118. package/dist/core/errors.d.ts +32 -0
  119. package/dist/core/errors.d.ts.map +1 -1
  120. package/dist/core/errors.js +81 -3
  121. package/dist/core/errors.js.map +1 -1
  122. package/dist/core/fs/prefix.d.ts +13 -0
  123. package/dist/core/fs/prefix.d.ts.map +1 -0
  124. package/dist/core/fs/prefix.js +22 -0
  125. package/dist/core/fs/prefix.js.map +1 -0
  126. package/dist/core/git/worktree.d.ts +22 -0
  127. package/dist/core/git/worktree.d.ts.map +1 -1
  128. package/dist/core/git/worktree.js +34 -0
  129. package/dist/core/git/worktree.js.map +1 -1
  130. package/dist/core/graph/persist.d.ts +13 -0
  131. package/dist/core/graph/persist.d.ts.map +1 -1
  132. package/dist/core/graph/persist.js +24 -0
  133. package/dist/core/graph/persist.js.map +1 -1
  134. package/dist/core/harness/isolated-run.d.ts +52 -0
  135. package/dist/core/harness/isolated-run.d.ts.map +1 -0
  136. package/dist/core/harness/isolated-run.js +100 -0
  137. package/dist/core/harness/isolated-run.js.map +1 -0
  138. package/dist/core/hooks.d.ts +3 -12
  139. package/dist/core/hooks.d.ts.map +1 -1
  140. package/dist/core/hooks.js +24 -20
  141. package/dist/core/hooks.js.map +1 -1
  142. package/dist/core/ingest/capture-hash.d.ts +16 -0
  143. package/dist/core/ingest/capture-hash.d.ts.map +1 -0
  144. package/dist/core/ingest/capture-hash.js +34 -0
  145. package/dist/core/ingest/capture-hash.js.map +1 -0
  146. package/dist/core/ingest/identity.d.ts +7 -1
  147. package/dist/core/ingest/identity.d.ts.map +1 -1
  148. package/dist/core/ingest/identity.js +16 -1
  149. package/dist/core/ingest/identity.js.map +1 -1
  150. package/dist/core/ingest/model.d.ts +17 -2
  151. package/dist/core/ingest/model.d.ts.map +1 -1
  152. package/dist/core/ingest/model.js +5 -0
  153. package/dist/core/ingest/model.js.map +1 -1
  154. package/dist/core/install-kind.d.ts +25 -0
  155. package/dist/core/install-kind.d.ts.map +1 -0
  156. package/dist/core/install-kind.js +56 -0
  157. package/dist/core/install-kind.js.map +1 -0
  158. package/dist/core/notes/list.d.ts +20 -0
  159. package/dist/core/notes/list.d.ts.map +1 -1
  160. package/dist/core/notes/list.js +27 -6
  161. package/dist/core/notes/list.js.map +1 -1
  162. package/dist/core/publish/script-check.d.ts +5 -2
  163. package/dist/core/publish/script-check.d.ts.map +1 -1
  164. package/dist/core/publish/script-check.js +5 -2
  165. package/dist/core/publish/script-check.js.map +1 -1
  166. package/dist/core/records.d.ts +7 -0
  167. package/dist/core/records.d.ts.map +1 -1
  168. package/dist/core/records.js +12 -2
  169. package/dist/core/records.js.map +1 -1
  170. package/dist/core/registry.d.ts +40 -0
  171. package/dist/core/registry.d.ts.map +1 -0
  172. package/dist/core/registry.js +55 -0
  173. package/dist/core/registry.js.map +1 -0
  174. package/dist/core/retrieval/pass.d.ts +66 -0
  175. package/dist/core/retrieval/pass.d.ts.map +1 -0
  176. package/dist/core/retrieval/pass.js +171 -0
  177. package/dist/core/retrieval/pass.js.map +1 -0
  178. package/dist/core/root.d.ts +11 -5
  179. package/dist/core/root.d.ts.map +1 -1
  180. package/dist/core/root.js +20 -8
  181. package/dist/core/root.js.map +1 -1
  182. package/dist/core/skills.d.ts.map +1 -1
  183. package/dist/core/skills.js +7 -0
  184. package/dist/core/skills.js.map +1 -1
  185. package/dist/core/version-check.d.ts +63 -0
  186. package/dist/core/version-check.d.ts.map +1 -0
  187. package/dist/core/version-check.js +181 -0
  188. package/dist/core/version-check.js.map +1 -0
  189. package/dist/core/write-lifecycle/path-gate.d.ts +2 -2
  190. package/dist/core/write-lifecycle/path-gate.d.ts.map +1 -1
  191. package/dist/core/write-lifecycle/path-gate.js +9 -10
  192. package/dist/core/write-lifecycle/path-gate.js.map +1 -1
  193. package/dist/run.d.ts +1 -6
  194. package/dist/run.d.ts.map +1 -1
  195. package/dist/run.js +76 -19
  196. package/dist/run.js.map +1 -1
  197. package/dist/version.d.ts +8 -1
  198. package/dist/version.d.ts.map +1 -1
  199. package/dist/version.js +8 -1
  200. package/dist/version.js.map +1 -1
  201. package/package.json +12 -4
  202. package/templates/agents/canonical.md +1 -1
  203. package/templates/agents/capture-and-ingest.md +27 -8
  204. package/templates/agents/retrieval-leg-routing.md +34 -8
  205. package/templates/hooks/_resolve-ctxr.sh +37 -0
  206. package/templates/hooks/claude-code-write-gate.sh +34 -6
  207. package/templates/hooks/pre-commit.sh +15 -8
  208. package/templates/serve/shell.html +16 -2
  209. package/templates/serve/style.css +145 -3
  210. package/templates/skills/ctxr-connection-finding.md +7 -5
  211. package/templates/skills/ctxr-ingest-orchestration.md +15 -9
  212. package/templates/skills/ctxr-publish.md +7 -8
  213. package/templates/skills/ctxr-session-lifecycle.md +20 -0
  214. package/templates/skills/ctxr-upgrade.md +44 -0
  215. package/dist/commands/migrate.d.ts +0 -30
  216. package/dist/commands/migrate.d.ts.map +0 -1
  217. package/dist/commands/migrate.js +0 -56
  218. package/dist/commands/migrate.js.map +0 -1
  219. package/dist/core/migrations/add-explanation-craft-skill.d.ts +0 -26
  220. package/dist/core/migrations/add-explanation-craft-skill.d.ts.map +0 -1
  221. package/dist/core/migrations/add-explanation-craft-skill.js +0 -94
  222. package/dist/core/migrations/add-explanation-craft-skill.js.map +0 -1
  223. package/dist/core/migrations/archive-destination-from-taxonomy.d.ts +0 -35
  224. package/dist/core/migrations/archive-destination-from-taxonomy.d.ts.map +0 -1
  225. package/dist/core/migrations/archive-destination-from-taxonomy.js +0 -109
  226. package/dist/core/migrations/archive-destination-from-taxonomy.js.map +0 -1
  227. package/dist/core/migrations/drop-access-axes.d.ts +0 -24
  228. package/dist/core/migrations/drop-access-axes.d.ts.map +0 -1
  229. package/dist/core/migrations/drop-access-axes.js +0 -54
  230. package/dist/core/migrations/drop-access-axes.js.map +0 -1
  231. package/dist/core/migrations/drop-forge-and-workspaces-external.d.ts +0 -19
  232. package/dist/core/migrations/drop-forge-and-workspaces-external.d.ts.map +0 -1
  233. package/dist/core/migrations/drop-forge-and-workspaces-external.js +0 -49
  234. package/dist/core/migrations/drop-forge-and-workspaces-external.js.map +0 -1
  235. package/dist/core/migrations/registry.d.ts +0 -16
  236. package/dist/core/migrations/registry.d.ts.map +0 -1
  237. package/dist/core/migrations/registry.js +0 -30
  238. package/dist/core/migrations/registry.js.map +0 -1
  239. package/dist/core/migrations/rename-conventions-path.d.ts +0 -26
  240. package/dist/core/migrations/rename-conventions-path.d.ts.map +0 -1
  241. package/dist/core/migrations/rename-conventions-path.js +0 -86
  242. package/dist/core/migrations/rename-conventions-path.js.map +0 -1
  243. package/dist/core/migrations/rename-procedures-path.d.ts +0 -17
  244. package/dist/core/migrations/rename-procedures-path.d.ts.map +0 -1
  245. package/dist/core/migrations/rename-procedures-path.js +0 -45
  246. package/dist/core/migrations/rename-procedures-path.js.map +0 -1
  247. package/dist/core/migrations/types.d.ts +0 -27
  248. package/dist/core/migrations/types.d.ts.map +0 -1
  249. package/dist/core/migrations/types.js +0 -2
  250. package/dist/core/migrations/types.js.map +0 -1
@@ -5,11 +5,13 @@ to synthesize an entity's current state from its sources, use `ctxr-rollup`.
5
5
  document it writes at `__GRAPH_DOCUMENT_PATH__` — hub notes by cluster, cross-cluster bridges,
6
6
  orphans — for the cluster context the point queries below do not summarize.
7
7
  2. To find what a note connects to or from, run `ctxr graph query neighbors <path>` (add `--depth` for
8
- further hops, `--direction in|out|both`, `--type <relation>` to follow one configured relation,
9
- `--as <context>` to see only what that context can see).
10
- 3. To find a path between two notes, run `ctxr graph query path <from> <to>`.
11
- 4. To find the most-referenced notes, run `ctxr graph query hubs`; to find unlinked ones,
8
+ further hops, `--direction in|out|both`, `--type <relation>` to follow one configured relation).
9
+ 3. To read a neighbourhood rather than enumerate one — every reachable note with its catalog gloss,
10
+ hop distance, and why it was reached — run `ctxr context gather --seed <path> --hops <n>`. Use it
11
+ when you need to judge which links matter; use the point queries below when you need the structure.
12
+ 4. To find a path between two notes, run `ctxr graph query path <from> <to>`.
13
+ 5. To find the most-referenced notes, run `ctxr graph query hubs`; to find unlinked ones,
12
14
  `ctxr graph query orphans`; `ctxr graph query clusters` and `ctxr graph query bridges` show the
13
15
  cluster structure and the notes that span it.
14
- 5. Report what the graph says — it enumerates structure and ranks nothing; judgment about which links
16
+ 6. Report what the graph says — it enumerates structure and ranks nothing; judgment about which links
15
17
  matter is yours.
@@ -1,15 +1,16 @@
1
1
  Ingest is synthesis, not filing. The question is what the store should know after this source, not where
2
2
  to put the file — "create a new note" is one option among several, never the default.
3
3
 
4
- 1. Capture: write a plain markdown file directly into the inbox (see AGENTS.md's capture section) — no
5
- provenance frontmatter; contexture assigns it at ingest.
4
+ 1. Capture: write the material into the inbox (see AGENTS.md's capture section). It may already carry
5
+ `source_type` and `source_id`; it must carry neither `source_hash` nor `ingested`, which ingest assigns.
6
+ The capture is kept — it is the store's record of what arrived, and it never becomes the note.
6
7
  2. Check: run `ctxr source check <path> --source-id <id>` and read the verdict — `new`, `already_ingested`,
7
8
  `drift` (same identity, the source's content moved — read what changed and decide whether to update the
8
9
  note, then `ctxr source stamp <path> --id <id>` once resolved), `alternate_source_match`, or
9
10
  `multiple_matches`. On `multiple_matches`, stop and resolve the ambiguity yourself; never guess which
10
- existing note it is. A legacy note with an identity but no hash on file: `ctxr source stamp` backfills
11
- it. A source re-published under a new URL you've confirmed is the same material:
12
- `ctxr source add-alt <path> --id <new-id>` on the existing note, not a second ingest.
11
+ existing record it is. A record with an identity but no hash on file: `ctxr source stamp` backfills it.
12
+ A source re-published under a new URL you've confirmed is the same material:
13
+ `ctxr source add-alt <path> --id <new-id>` on the existing capture, not a second ingest.
13
14
  3. Read the source fully. Then read the existing cluster BEFORE writing anything: the catalog section for
14
15
  the domain (`ctxr catalog show --section <id>`), every related note in it (all of them, not one or two),
15
16
  and the graph (`ctxr graph build`, then read the graph document it writes at
@@ -36,7 +37,12 @@ to put the file — "create a new note" is one option among several, never the d
36
37
  headline is worse than either alone.
37
38
  - Source discipline: a field the source does not confirm is "not reported" — never inferred from
38
39
  silence in either direction.
39
- 5. Write: for a new note, `ctxr ingest <path> --source-type <type> --source-id <id>` (stamps provenance and
40
- gives it a catalog entry). Updates to existing notes are ordinary edits that preserve prior content
41
- (a deliberate ingest despite an `alternate_source_match` is the same command).
42
- 6. Verify: `ctxr lint` (orphans, broken links, leftover inbox material) and `ctxr catalog check`.
40
+ 5. Write the note the decision calls for — create it, expand it, merge, restructure, or add a section —
41
+ preserving prior content in every case but the deliberate rewrite.
42
+ 6. Register the source against whatever note you just wrote:
43
+ `ctxr ingest <path> --into <note> --source-type <type> --source-id <id>`. Every row of the table above
44
+ ends here, not just the first: the command retains the capture under the capture tier's month, freezes
45
+ its hash, cites it from the note, and rebuilds the catalog. A note that was expanded rather than created
46
+ records its provenance exactly as a new one does, and a note built from several sources cites all of
47
+ them. A deliberate ingest despite an `alternate_source_match` is the same command.
48
+ 7. Verify: `ctxr lint` (orphans, broken links, material still in the inbox) and `ctxr catalog check`.
@@ -1,7 +1,6 @@
1
- Turn store content into a shareable HTML page for a subject — a store subtree, a single note, a
2
- concept whose sources aren't co-located, or everything a named context admits. The gate below is the
3
- one step no convention can enforce by itself; everything else here is a decision procedure, not a
4
- mechanism.
1
+ Turn store content into a shareable HTML page for a subject — a store subtree, a single note, or a
2
+ concept whose sources aren't co-located. Deciding what belongs on the page is the one step no
3
+ convention can enforce for you; everything else here is a decision procedure, not a mechanism.
5
4
 
6
5
  ## 1. Does this earn a page over a note?
7
6
 
@@ -51,10 +50,10 @@ notes came from, so the notes' shorthand does not survive the copy out. Load the
51
50
  store carries by default (or whichever explanation-focused skill it's configured instead), settle who
52
51
  the reader is before writing, and pitch every definition, analogy, and level of detail at them.
53
52
 
54
- Both skills say "audience", and neither means step 3's. There, `--audience` names who the store is
55
- being asked to disclose to and the answer is a verdict; here it names how much a reader already knows
56
- and the answer is a register. A comprehension level is never a value you pass to `--audience`, and
57
- writing plainly never widens what the page may contain — the gate in step 3 already settled that.
53
+ Both skills say "audience", and here it means one thing only: how much the reader already knows,
54
+ which is a question about register. It is never a reason to put more on the page. Step 3 settled what
55
+ the page may carry, and writing that content more plainly never widens it — an explanation pitched
56
+ lower is the same material in shorter words.
58
57
 
59
58
  ## 6. Verify the output invariants
60
59
 
@@ -9,6 +9,26 @@ the two verbs at the seams; their steps are not repeated here.
9
9
  If you find yourself on the default branch or in the root checkout, stop — `ctxr session list` shows the
10
10
  active sessions to work in instead.
11
11
 
12
+ Before starting, bring the store's canonical clone up to date — the repository's main worktree, not
13
+ whichever checkout you are standing in. From the canonical clone: `git fetch origin`, then
14
+ `git merge --ff-only origin/__DEFAULT_BRANCH__`. If it is on another branch, carries uncommitted
15
+ changes, or the fast-forward fails because it has diverged from origin, report exactly that and start
16
+ the session anyway — never check it out, reset it, stash, or force the merge to make it comply. The
17
+ session's base is unaffected either way, because `ctxr session start` branches from the
18
+ `origin/__DEFAULT_BRANCH__` it fetches itself. What a stale clone costs is the context you read out of
19
+ it: notes, catalog sections, the graph document, and AGENTS.md would all be the versions it last had.
20
+
21
+ `ctxr session start` names the start point it used. If it reports that it did not fetch, there was no
22
+ remote branch to fetch from and it branched from the local default branch instead — say so plainly,
23
+ because the session is then based on whatever that clone last had rather than on origin.
24
+
25
+ If `ctxr session start` reports a `cli.update_available` finding, a newer `ctxr` than the one installed
26
+ has been published. Name both versions to the operator and offer `ctxr-upgrade`; then continue the
27
+ session either way. Do not upgrade unasked, and do not make continuing conditional on the answer —
28
+ deferring is a normal answer, and the session is unaffected by it. A `cli.update_check_failed` finding
29
+ means the check could not be completed; it says nothing about whether an upgrade is due, so proceed
30
+ without mentioning it.
31
+
12
32
  ## Re-scan before any plan
13
33
 
14
34
  Re-scan whenever state may have moved under you — before presenting a plan, before running `ctxr-submit`,
@@ -0,0 +1,44 @@
1
+ Upgrade the installed `ctxr` to the latest published release, then bring this store's
2
+ contexture-owned files up to it. `ctxr-session-lifecycle` offers this skill at the start of a session
3
+ when a newer release is published; it is equally valid to run it directly.
4
+
5
+ Upgrading replaces the executable for every store on this machine, not only this one. That is why
6
+ step 3 gates on the operator rather than proceeding from the fact that a newer release exists.
7
+
8
+ 1. Read the live answer — never act on a notice from earlier in the conversation, which may be
9
+ minutes stale: `ctxr version --check --json`. The envelope's `data` carries `version` (installed),
10
+ `latest` (published), `release_status`, `install_path`, and `install_kind`. Exit code `0` means
11
+ already current: say so and stop. A non-zero exit with `release_status` of `undetermined` means the
12
+ published version could not be resolved — report the reason the finding names, and stop; do not
13
+ guess whether an upgrade is due.
14
+
15
+ 2. Check `install_kind` before proposing anything.
16
+ - `global` — proceed to step 3.
17
+ - `linked` — this executable resolves to a working copy at `install_path`, not a package
18
+ installation. A global install would upgrade a different `ctxr` than the one running. Report the
19
+ path and stop.
20
+ - `undetermined` — the executable is inside a `node_modules` that is not the global one: a project
21
+ dependency, or an `npx` invocation. Report `install_path` and stop; upgrading it is the
22
+ operator's call about that project, not a global install.
23
+
24
+ 3. Gate on the operator. Name the installed version, the published version, and `install_path`, and
25
+ ask whether to upgrade. Wait for an explicit go. Having approval for the session's other work is
26
+ not approval for this — it changes software outside the store.
27
+
28
+ 4. Upgrade, then confirm: `npm install -g ctxr-cli@latest`, then `ctxr version`. Confirm the reported
29
+ version is the published one before continuing. If it still reports the old version, the shell is
30
+ resolving a different `ctxr` than the one npm wrote — report that and stop rather than continuing
31
+ into step 5, where the re-render would be performed by the executable you just tried to replace.
32
+
33
+ 5. Re-render this store with the upgraded executable, in that order — the generated files come from
34
+ the binary, so re-rendering first would only rewrite them at the old version. Work in a session
35
+ worktree (`ctxr session start`), never the root checkout: `ctxr update` writes contexture-owned
36
+ files, and those writes land through a reviewed pull request like any other change.
37
+
38
+ 6. Land the re-render as its own pull request. `ctxr update` produces generated-file churn — AGENTS.md
39
+ sections, skill copies, hooks, adapter outputs — and mixing it into unrelated work makes both
40
+ harder to review. Follow `ctxr-submit`, then `ctxr-land`.
41
+
42
+ If step 4 or 5 fails, say which step and what the command reported. A partial upgrade — new executable,
43
+ un-re-rendered store — is a real state worth naming: the store still works, and step 5 can be re-run on
44
+ its own at any time.
@@ -1,30 +0,0 @@
1
- import type { CommandOutcome, CommandRequires } from '../core/command.js';
2
- import type { MigrationDelta } from '../core/migrations/types.js';
3
- import type { Store } from '../core/store.js';
4
- export declare const requires: CommandRequires;
5
- export interface MigrateFlags {
6
- dryRun?: boolean;
7
- }
8
- export interface MigrateMigrationResult {
9
- id: string;
10
- fromVersion: number;
11
- toVersion: number;
12
- deltas: MigrationDelta[];
13
- }
14
- export interface MigrateData {
15
- currentVersion: number;
16
- targetVersion: number;
17
- applied: boolean;
18
- migrations: MigrateMigrationResult[];
19
- }
20
- /**
21
- * store-lifecycle spec: `--dry-run` reports exact deltas with nothing
22
- * applied; a real run applies each pending migration in order, reloading
23
- * the store's config after each one so a later migration in the chain
24
- * (none exist yet, but the mechanism supports it) sees the version it
25
- * actually needs to start from. Resumability is a property of each
26
- * migration's own plan()/apply() (see core/migrations/types.ts) — this
27
- * command does no extra bookkeeping of its own.
28
- */
29
- export declare function execute(store: Store, flags: MigrateFlags): Promise<CommandOutcome<MigrateData>>;
30
- //# sourceMappingURL=migrate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,eAAuC,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,sBAAsB,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CA4CrG"}
@@ -1,56 +0,0 @@
1
- import { readConfig } from '../config/load.js';
2
- import { SUPPORTED_SCHEMA_VERSION } from '../config/schema.js';
3
- import { ExitCode } from '../core/exit-codes.js';
4
- import { pendingMigrations } from '../core/migrations/registry.js';
5
- export const requires = { store: 'required' };
6
- /**
7
- * store-lifecycle spec: `--dry-run` reports exact deltas with nothing
8
- * applied; a real run applies each pending migration in order, reloading
9
- * the store's config after each one so a later migration in the chain
10
- * (none exist yet, but the mechanism supports it) sees the version it
11
- * actually needs to start from. Resumability is a property of each
12
- * migration's own plan()/apply() (see core/migrations/types.ts) — this
13
- * command does no extra bookkeeping of its own.
14
- */
15
- export async function execute(store, flags) {
16
- const pending = pendingMigrations(store.config.schema_version);
17
- const startingVersion = store.config.schema_version;
18
- if (pending.length === 0) {
19
- return {
20
- exitCode: ExitCode.Ok,
21
- data: { currentVersion: startingVersion, targetVersion: SUPPORTED_SCHEMA_VERSION, applied: false, migrations: [] },
22
- findings: [],
23
- humanSummary: `Already at schema_version ${startingVersion}; nothing to migrate.`,
24
- storeRoot: store.root,
25
- schemaVersion: store.config.schema_version,
26
- };
27
- }
28
- const results = [];
29
- let workingStore = store;
30
- for (const migration of pending) {
31
- if (flags.dryRun) {
32
- const deltas = await migration.plan(workingStore);
33
- results.push({ id: migration.id, fromVersion: migration.fromVersion, toVersion: migration.toVersion, deltas });
34
- continue;
35
- }
36
- const deltas = await migration.apply(workingStore);
37
- results.push({ id: migration.id, fromVersion: migration.fromVersion, toVersion: migration.toVersion, deltas });
38
- workingStore = { root: workingStore.root, config: await readConfig(workingStore.root) };
39
- }
40
- return {
41
- exitCode: ExitCode.Ok,
42
- data: {
43
- currentVersion: startingVersion,
44
- targetVersion: SUPPORTED_SCHEMA_VERSION,
45
- applied: !flags.dryRun,
46
- migrations: results,
47
- },
48
- findings: [],
49
- humanSummary: flags.dryRun
50
- ? `--dry-run: ${results.reduce((n, r) => n + r.deltas.length, 0)} change(s) would be made across ${results.length} migration(s).`
51
- : `Applied ${results.length} migration(s), now at schema_version ${workingStore.config.schema_version}.`,
52
- storeRoot: store.root,
53
- schemaVersion: flags.dryRun ? store.config.schema_version : workingStore.config.schema_version,
54
- };
55
- }
56
- //# sourceMappingURL=migrate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"}
@@ -1,26 +0,0 @@
1
- import type { Migration } from './types.js';
2
- /**
3
- * vendor-explanation-craft-skill: the shipped vendored set grew a second craft
4
- * skill, and `init` writes the RESOLVED list into `contexture.yaml` while
5
- * `reconcileStore` never rewrites configuration. So a change to the shipped
6
- * default reaches new stores only; without this migration every store already
7
- * on disk would keep a one-entry list and silently never receive the skill the
8
- * publish skill now tells it to load.
9
- *
10
- * The uncomfortable part, stated rather than implied: `config/schema.ts` says
11
- * the schema version bumps "only on a genuinely incompatible change, never on
12
- * an additive one," and adding a skill is additive. This bumps it anyway, which
13
- * means every existing store reports as needing `ctxr migrate` because a skill
14
- * was added. That was the accepted price of guaranteed propagation — the
15
- * alternatives were leaving the shipped default a lie for every store predating
16
- * it, or an update-time nag that would never stop firing in a store that
17
- * deliberately opted out. Do not read this as license to bump the version for
18
- * the next additive change; weigh that one on its own.
19
- *
20
- * Pending-ness is the recorded schema version, never the list's contents — the
21
- * rule 0002, 0004, 0005, and 0006 all follow, because the config schema fills
22
- * `skills.vendored` from the shipped default when the key is absent, so an
23
- * unmigrated store already reads as though it declared the new set.
24
- */
25
- export declare const addExplanationCraftSkillMigration: Migration;
26
- //# sourceMappingURL=add-explanation-craft-skill.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"add-explanation-craft-skill.d.ts","sourceRoot":"","sources":["../../../src/core/migrations/add-explanation-craft-skill.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AA6C5D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,iCAAiC,EAAE,SA8B/C,CAAC"}
@@ -1,94 +0,0 @@
1
- import path from 'node:path';
2
- import { DEFAULT_VENDORED_SKILLS } from '../../config/defaults.js';
3
- import { readConfig } from '../../config/load.js';
4
- import { renderStoreConfig } from '../../config/render.js';
5
- import { writeFileAtomic } from '../fs/atomic.js';
6
- /**
7
- * The shipped set as it stood before this change — a fixed historical literal,
8
- * never derived from `DEFAULT_VENDORED_SKILLS`. Deriving it would make the
9
- * "was this list ever customized?" test drift every time the shipped set grows
10
- * again, silently re-adding to lists a later operator had curated.
11
- */
12
- const PREVIOUS_SHIPPED_SET = ['frontend-design'];
13
- const SCHEMA_VERSION = 7;
14
- function configDelta(next) {
15
- return {
16
- path: 'contexture.yaml',
17
- description: `set skills.vendored to [${next.join(', ')}] and schema_version to ${SCHEMA_VERSION}`,
18
- };
19
- }
20
- function versionOnlyDelta() {
21
- return {
22
- path: 'contexture.yaml',
23
- description: `set schema_version to ${SCHEMA_VERSION}, leaving this store's own skills.vendored list untouched`,
24
- };
25
- }
26
- /**
27
- * The list to write, or undefined when this store's is not ours to rewrite.
28
- *
29
- * The heuristic 0004 and 0006 both used: a list still sitting exactly on the
30
- * previous shipped default was never curated, so growing it matches what the
31
- * operator already accepted. A list that was reordered, added to, or emptied to
32
- * opt out is a decision, and re-adding to it would overwrite that decision —
33
- * such a store gets the version bump alone.
34
- */
35
- function nextVendoredList(current) {
36
- const unchanged = current.length === PREVIOUS_SHIPPED_SET.length && current.every((name, i) => name === PREVIOUS_SHIPPED_SET[i]);
37
- if (!unchanged)
38
- return undefined;
39
- const shipped = [...DEFAULT_VENDORED_SKILLS];
40
- const added = shipped.filter((name) => !current.includes(name));
41
- return added.length > 0 ? shipped : undefined;
42
- }
43
- /**
44
- * vendor-explanation-craft-skill: the shipped vendored set grew a second craft
45
- * skill, and `init` writes the RESOLVED list into `contexture.yaml` while
46
- * `reconcileStore` never rewrites configuration. So a change to the shipped
47
- * default reaches new stores only; without this migration every store already
48
- * on disk would keep a one-entry list and silently never receive the skill the
49
- * publish skill now tells it to load.
50
- *
51
- * The uncomfortable part, stated rather than implied: `config/schema.ts` says
52
- * the schema version bumps "only on a genuinely incompatible change, never on
53
- * an additive one," and adding a skill is additive. This bumps it anyway, which
54
- * means every existing store reports as needing `ctxr migrate` because a skill
55
- * was added. That was the accepted price of guaranteed propagation — the
56
- * alternatives were leaving the shipped default a lie for every store predating
57
- * it, or an update-time nag that would never stop firing in a store that
58
- * deliberately opted out. Do not read this as license to bump the version for
59
- * the next additive change; weigh that one on its own.
60
- *
61
- * Pending-ness is the recorded schema version, never the list's contents — the
62
- * rule 0002, 0004, 0005, and 0006 all follow, because the config schema fills
63
- * `skills.vendored` from the shipped default when the key is absent, so an
64
- * unmigrated store already reads as though it declared the new set.
65
- */
66
- export const addExplanationCraftSkillMigration = {
67
- id: '0007-add-explanation-craft-skill',
68
- fromVersion: 6,
69
- toVersion: SCHEMA_VERSION,
70
- description: `Add the explanation craft skill to a store whose skills.vendored list still sits at the previous shipped default, and bump schema_version to ${SCHEMA_VERSION}.`,
71
- async plan(store) {
72
- if (store.config.schema_version >= SCHEMA_VERSION)
73
- return [];
74
- const next = nextVendoredList(store.config.skills.vendored);
75
- return [next ? configDelta(next) : versionOnlyDelta()];
76
- },
77
- async apply(store) {
78
- if (store.config.schema_version >= SCHEMA_VERSION)
79
- return [];
80
- // Re-read from disk rather than trusting the store snapshot: an interrupted
81
- // run may have written the config already, and resumability means deciding
82
- // from current state.
83
- const currentConfig = await readConfig(store.root);
84
- const next = nextVendoredList(currentConfig.skills.vendored);
85
- const nextConfig = {
86
- ...currentConfig,
87
- schema_version: SCHEMA_VERSION,
88
- skills: { ...currentConfig.skills, vendored: next ?? currentConfig.skills.vendored },
89
- };
90
- await writeFileAtomic(path.join(store.root, 'contexture.yaml'), renderStoreConfig(nextConfig));
91
- return [next ? configDelta(next) : versionOnlyDelta()];
92
- },
93
- };
94
- //# sourceMappingURL=add-explanation-craft-skill.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"add-explanation-craft-skill.js","sourceRoot":"","sources":["../../../src/core/migrations/add-explanation-craft-skill.ts"],"names":[],"mappings":"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"}
@@ -1,35 +0,0 @@
1
- import type { Migration } from './types.js';
2
- /**
3
- * archive-destination-from-taxonomy: `ctxr init` wrote a fixed
4
- * `DEFAULT_ARCHIVE_PATH` regardless of the taxonomy it had just resolved, so
5
- * every PARA store was born with `archive/` while its own taxonomy declared
6
- * `archives/` — a config key pointing at a directory the store does not have.
7
- * Init now asks the profile; this migration does the same for stores already
8
- * on disk.
9
- *
10
- * Two independent halves, and the second is conditional:
11
- *
12
- * 1. The key rename is unconditional — every schema-5 store gets
13
- * `archive_destination`. `OrganizeSchema`'s fallback transform has already
14
- * resolved the old spelling by the time `readConfig` returns, so writing
15
- * the parsed config back is what drops `archive_path` from disk.
16
- * 2. The value only changes when the store never customized it AND its
17
- * profile declares a destination of its own. An operator who deliberately
18
- * set some other path keeps it; a Zettelkasten or Diataxis store, whose
19
- * profile declares none, keeps `archive/` — for them this is a pure key
20
- * rename. A custom taxonomy resolves to no shipped profile and is left
21
- * alone for the same reason.
22
- *
23
- * Like 0004, the directory move is a plain filesystem rename (migrations see
24
- * only `Store` — `root` + `config`, no `GitRunner`), and it is skipped when
25
- * the old directory was never created. History survives either way: whatever
26
- * commits this output stages a coherent delete-old/add-new diff, which
27
- * `git log --follow`'s rename detection reads identically to a `git mv`.
28
- *
29
- * Pending-ness is `schema_version < 6`, not key presence — the rule 0002,
30
- * 0004, and 0005 established, for the same reason: the fallback transform
31
- * populates `archive_destination` on an unmigrated store too, so its presence
32
- * cannot distinguish migrated from not.
33
- */
34
- export declare const archiveDestinationFromTaxonomyMigration: Migration;
35
- //# sourceMappingURL=archive-destination-from-taxonomy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"archive-destination-from-taxonomy.d.ts","sourceRoot":"","sources":["../../../src/core/migrations/archive-destination-from-taxonomy.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AAc5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,uCAAuC,EAAE,SA4CrD,CAAC"}
@@ -1,109 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { rename } from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { readConfig } from '../../config/load.js';
5
- import { DEFAULT_ARCHIVE_DESTINATION } from '../../config/defaults.js';
6
- import { renderStoreConfig } from '../../config/render.js';
7
- import { profileById } from '../../taxonomy/profiles.js';
8
- import { writeFileAtomic } from '../fs/atomic.js';
9
- const CONFIG_DELTA = {
10
- path: 'contexture.yaml',
11
- description: 'rename organize.archive_path to organize.archive_destination and set schema_version to 6',
12
- };
13
- function destinationDelta(from, to) {
14
- return {
15
- path: to,
16
- description: `adopt the taxonomy's own archive destination, moving the default-valued archive directory from ${from} to ${to}`,
17
- };
18
- }
19
- /**
20
- * archive-destination-from-taxonomy: `ctxr init` wrote a fixed
21
- * `DEFAULT_ARCHIVE_PATH` regardless of the taxonomy it had just resolved, so
22
- * every PARA store was born with `archive/` while its own taxonomy declared
23
- * `archives/` — a config key pointing at a directory the store does not have.
24
- * Init now asks the profile; this migration does the same for stores already
25
- * on disk.
26
- *
27
- * Two independent halves, and the second is conditional:
28
- *
29
- * 1. The key rename is unconditional — every schema-5 store gets
30
- * `archive_destination`. `OrganizeSchema`'s fallback transform has already
31
- * resolved the old spelling by the time `readConfig` returns, so writing
32
- * the parsed config back is what drops `archive_path` from disk.
33
- * 2. The value only changes when the store never customized it AND its
34
- * profile declares a destination of its own. An operator who deliberately
35
- * set some other path keeps it; a Zettelkasten or Diataxis store, whose
36
- * profile declares none, keeps `archive/` — for them this is a pure key
37
- * rename. A custom taxonomy resolves to no shipped profile and is left
38
- * alone for the same reason.
39
- *
40
- * Like 0004, the directory move is a plain filesystem rename (migrations see
41
- * only `Store` — `root` + `config`, no `GitRunner`), and it is skipped when
42
- * the old directory was never created. History survives either way: whatever
43
- * commits this output stages a coherent delete-old/add-new diff, which
44
- * `git log --follow`'s rename detection reads identically to a `git mv`.
45
- *
46
- * Pending-ness is `schema_version < 6`, not key presence — the rule 0002,
47
- * 0004, and 0005 established, for the same reason: the fallback transform
48
- * populates `archive_destination` on an unmigrated store too, so its presence
49
- * cannot distinguish migrated from not.
50
- */
51
- export const archiveDestinationFromTaxonomyMigration = {
52
- id: '0006-archive-destination-from-taxonomy',
53
- fromVersion: 5,
54
- toVersion: 6,
55
- description: "Rename the organize.archive_path config key to organize.archive_destination, adopt the taxonomy profile's own archive destination when the value still sat at the shipped default, and bump schema_version to 6.",
56
- async plan(store) {
57
- if (store.config.schema_version >= 6)
58
- return [];
59
- const deltas = [CONFIG_DELTA];
60
- const target = taxonomyDestination(store.config.taxonomy.profile, store.config.organize.archive_destination);
61
- if (target)
62
- deltas.push(destinationDelta(DEFAULT_ARCHIVE_DESTINATION, target));
63
- return deltas;
64
- },
65
- async apply(store) {
66
- if (store.config.schema_version >= 6)
67
- return [];
68
- const configPath = path.join(store.root, 'contexture.yaml');
69
- const currentConfig = await readConfig(store.root);
70
- const appliedDeltas = [CONFIG_DELTA];
71
- let destination = currentConfig.organize.archive_destination;
72
- const target = taxonomyDestination(currentConfig.taxonomy.profile, destination);
73
- if (target) {
74
- const oldDir = path.join(store.root, DEFAULT_ARCHIVE_DESTINATION);
75
- const newDir = path.join(store.root, target);
76
- // Absent whenever nothing was ever archived — only the config changes.
77
- if (existsSync(oldDir) && !existsSync(newDir)) {
78
- await rename(oldDir, newDir);
79
- }
80
- destination = target;
81
- appliedDeltas.push(destinationDelta(DEFAULT_ARCHIVE_DESTINATION, target));
82
- }
83
- const nextConfig = {
84
- ...currentConfig,
85
- schema_version: 6,
86
- organize: { ...currentConfig.organize, archive_destination: destination },
87
- };
88
- await writeFileAtomic(configPath, renderStoreConfig(nextConfig));
89
- return appliedDeltas;
90
- },
91
- };
92
- /**
93
- * The profile's own destination, but only when adopting it is safe: the
94
- * store must still be sitting on the shipped default (otherwise the value is
95
- * the operator's, not ours to rewrite), the profile must be a shipped one
96
- * that declares a destination, and it must actually differ from what's
97
- * already configured.
98
- */
99
- function taxonomyDestination(profileId, current) {
100
- if (current !== DEFAULT_ARCHIVE_DESTINATION)
101
- return undefined;
102
- if (profileId === null)
103
- return undefined;
104
- const declared = profileById(profileId)?.archiveDestination;
105
- if (declared === undefined || declared === current)
106
- return undefined;
107
- return declared;
108
- }
109
- //# sourceMappingURL=archive-destination-from-taxonomy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"archive-destination-from-taxonomy.js","sourceRoot":"","sources":["../../../src/core/migrations/archive-destination-from-taxonomy.ts"],"names":[],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- import type { Migration } from './types.js';
2
- /**
3
- * retire-the-access-axes: the visibility and disclosure axes are removed, and
4
- * with them `fields.visibility` (the configurable name of the visibility
5
- * frontmatter key).
6
- *
7
- * Unlike 0005, this migration cannot lean on `readConfig` having already
8
- * stripped the legacy shape: all three keys are TOP-LEVEL, and
9
- * `StoreConfigSchema` is `.passthrough()`, so they survive parsing intact.
10
- * Deleting them explicitly is the whole job.
11
- *
12
- * No note is rewritten (design.md D3). A note's retired visibility-field key
13
- * stays in its frontmatter, unread — `parseNote` reads frontmatter into a
14
- * `Record<string, unknown>` and nothing consumes that key any more, so it
15
- * costs nothing at runtime and keeps the removal cheap to reverse. Stripping
16
- * it would make re-entry a hand re-labelling pass over every note.
17
- *
18
- * Pending-ness is `schema_version < 8`, not key presence — the rule every
19
- * migration from 0002 onward established. A store could have had its config
20
- * hand-edited to drop the keys while still sitting at an older version, and
21
- * it still needs the version bump.
22
- */
23
- export declare const dropAccessAxesMigration: Migration;
24
- //# sourceMappingURL=drop-access-axes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drop-access-axes.d.ts","sourceRoot":"","sources":["../../../src/core/migrations/drop-access-axes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AAU5D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAuBrC,CAAC"}