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.
- package/README.md +313 -22
- package/dist/adapters/types.d.ts +0 -5
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/commands/adapters-generate.d.ts.map +1 -1
- package/dist/commands/adapters-generate.js +2 -3
- package/dist/commands/adapters-generate.js.map +1 -1
- package/dist/commands/context-gather.d.ts +22 -0
- package/dist/commands/context-gather.d.ts.map +1 -0
- package/dist/commands/context-gather.js +36 -0
- package/dist/commands/context-gather.js.map +1 -0
- package/dist/commands/graph-query.d.ts.map +1 -1
- package/dist/commands/graph-query.js +6 -8
- package/dist/commands/graph-query.js.map +1 -1
- package/dist/commands/ingest.d.ts +22 -9
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +86 -24
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +22 -5
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/publish-check.d.ts.map +1 -1
- package/dist/commands/publish-check.js +8 -0
- package/dist/commands/publish-check.js.map +1 -1
- package/dist/commands/publish-new.d.ts.map +1 -1
- package/dist/commands/publish-new.js +15 -0
- package/dist/commands/publish-new.js.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +33 -11
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/session-start.d.ts.map +1 -1
- package/dist/commands/session-start.js +9 -1
- package/dist/commands/session-start.js.map +1 -1
- package/dist/commands/source-check.d.ts.map +1 -1
- package/dist/commands/source-check.js +52 -9
- package/dist/commands/source-check.js.map +1 -1
- package/dist/commands/source-stamp.d.ts +6 -5
- package/dist/commands/source-stamp.d.ts.map +1 -1
- package/dist/commands/source-stamp.js +8 -7
- package/dist/commands/source-stamp.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +7 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/verify.d.ts +11 -2
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +86 -5
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/version.d.ts +31 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +87 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/config/defaults.d.ts +113 -4
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +83 -4
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/load.d.ts +2 -2
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +13 -3
- package/dist/config/load.js.map +1 -1
- package/dist/config/render.d.ts +5 -0
- package/dist/config/render.d.ts.map +1 -1
- package/dist/config/render.js +62 -3
- package/dist/config/render.js.map +1 -1
- package/dist/config/schema.d.ts +47 -76
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +171 -134
- package/dist/config/schema.js.map +1 -1
- package/dist/core/agents-doc.d.ts.map +1 -1
- package/dist/core/agents-doc.js +4 -1
- package/dist/core/agents-doc.js.map +1 -1
- package/dist/core/browse/nav.d.ts.map +1 -1
- package/dist/core/browse/nav.js +4 -1
- package/dist/core/browse/nav.js.map +1 -1
- package/dist/core/browse/preferences.d.ts +26 -0
- package/dist/core/browse/preferences.d.ts.map +1 -0
- package/dist/core/browse/preferences.js +74 -0
- package/dist/core/browse/preferences.js.map +1 -0
- package/dist/core/browse/routes.d.ts +10 -8
- package/dist/core/browse/routes.d.ts.map +1 -1
- package/dist/core/browse/routes.js +113 -24
- package/dist/core/browse/routes.js.map +1 -1
- package/dist/core/browse/templates.d.ts +14 -4
- package/dist/core/browse/templates.d.ts.map +1 -1
- package/dist/core/browse/templates.js +22 -4
- package/dist/core/browse/templates.js.map +1 -1
- package/dist/core/checks/harness-portability-checks.d.ts +22 -1
- package/dist/core/checks/harness-portability-checks.d.ts.map +1 -1
- package/dist/core/checks/harness-portability-checks.js +48 -4
- package/dist/core/checks/harness-portability-checks.js.map +1 -1
- package/dist/core/checks/integrity-checks.d.ts +0 -2
- package/dist/core/checks/integrity-checks.d.ts.map +1 -1
- package/dist/core/checks/integrity-checks.js +2 -27
- package/dist/core/checks/integrity-checks.js.map +1 -1
- package/dist/core/checks/manifest.d.ts.map +1 -1
- package/dist/core/checks/manifest.js +2 -0
- package/dist/core/checks/manifest.js.map +1 -1
- package/dist/core/checks/organize-checks.d.ts +11 -1
- package/dist/core/checks/organize-checks.d.ts.map +1 -1
- package/dist/core/checks/organize-checks.js +42 -12
- package/dist/core/checks/organize-checks.js.map +1 -1
- package/dist/core/checks/retrieval-checks.d.ts +9 -0
- package/dist/core/checks/retrieval-checks.d.ts.map +1 -0
- package/dist/core/checks/retrieval-checks.js +30 -0
- package/dist/core/checks/retrieval-checks.js.map +1 -0
- package/dist/core/command.d.ts +6 -0
- package/dist/core/command.d.ts.map +1 -1
- package/dist/core/content/canonicalize.d.ts +10 -0
- package/dist/core/content/canonicalize.d.ts.map +1 -1
- package/dist/core/content/canonicalize.js +12 -0
- package/dist/core/content/canonicalize.js.map +1 -1
- package/dist/core/env.d.ts +5 -0
- package/dist/core/env.d.ts.map +1 -1
- package/dist/core/env.js +3 -0
- package/dist/core/env.js.map +1 -1
- package/dist/core/environment/probe.d.ts +12 -0
- package/dist/core/environment/probe.d.ts.map +1 -0
- package/dist/core/environment/probe.js +36 -0
- package/dist/core/environment/probe.js.map +1 -0
- package/dist/core/errors.d.ts +32 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +81 -3
- package/dist/core/errors.js.map +1 -1
- package/dist/core/fs/prefix.d.ts +13 -0
- package/dist/core/fs/prefix.d.ts.map +1 -0
- package/dist/core/fs/prefix.js +22 -0
- package/dist/core/fs/prefix.js.map +1 -0
- package/dist/core/git/worktree.d.ts +22 -0
- package/dist/core/git/worktree.d.ts.map +1 -1
- package/dist/core/git/worktree.js +34 -0
- package/dist/core/git/worktree.js.map +1 -1
- package/dist/core/graph/persist.d.ts +13 -0
- package/dist/core/graph/persist.d.ts.map +1 -1
- package/dist/core/graph/persist.js +24 -0
- package/dist/core/graph/persist.js.map +1 -1
- package/dist/core/harness/isolated-run.d.ts +52 -0
- package/dist/core/harness/isolated-run.d.ts.map +1 -0
- package/dist/core/harness/isolated-run.js +100 -0
- package/dist/core/harness/isolated-run.js.map +1 -0
- package/dist/core/hooks.d.ts +3 -12
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +24 -20
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/ingest/capture-hash.d.ts +16 -0
- package/dist/core/ingest/capture-hash.d.ts.map +1 -0
- package/dist/core/ingest/capture-hash.js +34 -0
- package/dist/core/ingest/capture-hash.js.map +1 -0
- package/dist/core/ingest/identity.d.ts +7 -1
- package/dist/core/ingest/identity.d.ts.map +1 -1
- package/dist/core/ingest/identity.js +16 -1
- package/dist/core/ingest/identity.js.map +1 -1
- package/dist/core/ingest/model.d.ts +17 -2
- package/dist/core/ingest/model.d.ts.map +1 -1
- package/dist/core/ingest/model.js +5 -0
- package/dist/core/ingest/model.js.map +1 -1
- package/dist/core/install-kind.d.ts +25 -0
- package/dist/core/install-kind.d.ts.map +1 -0
- package/dist/core/install-kind.js +56 -0
- package/dist/core/install-kind.js.map +1 -0
- package/dist/core/notes/list.d.ts +20 -0
- package/dist/core/notes/list.d.ts.map +1 -1
- package/dist/core/notes/list.js +27 -6
- package/dist/core/notes/list.js.map +1 -1
- package/dist/core/publish/script-check.d.ts +5 -2
- package/dist/core/publish/script-check.d.ts.map +1 -1
- package/dist/core/publish/script-check.js +5 -2
- package/dist/core/publish/script-check.js.map +1 -1
- package/dist/core/records.d.ts +7 -0
- package/dist/core/records.d.ts.map +1 -1
- package/dist/core/records.js +12 -2
- package/dist/core/records.js.map +1 -1
- package/dist/core/registry.d.ts +40 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +55 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/retrieval/pass.d.ts +66 -0
- package/dist/core/retrieval/pass.d.ts.map +1 -0
- package/dist/core/retrieval/pass.js +171 -0
- package/dist/core/retrieval/pass.js.map +1 -0
- package/dist/core/root.d.ts +11 -5
- package/dist/core/root.d.ts.map +1 -1
- package/dist/core/root.js +20 -8
- package/dist/core/root.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +7 -0
- package/dist/core/skills.js.map +1 -1
- package/dist/core/version-check.d.ts +63 -0
- package/dist/core/version-check.d.ts.map +1 -0
- package/dist/core/version-check.js +181 -0
- package/dist/core/version-check.js.map +1 -0
- package/dist/core/write-lifecycle/path-gate.d.ts +2 -2
- package/dist/core/write-lifecycle/path-gate.d.ts.map +1 -1
- package/dist/core/write-lifecycle/path-gate.js +9 -10
- package/dist/core/write-lifecycle/path-gate.js.map +1 -1
- package/dist/run.d.ts +1 -6
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +76 -19
- package/dist/run.js.map +1 -1
- package/dist/version.d.ts +8 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +8 -1
- package/dist/version.js.map +1 -1
- package/package.json +12 -4
- package/templates/agents/canonical.md +1 -1
- package/templates/agents/capture-and-ingest.md +27 -8
- package/templates/agents/retrieval-leg-routing.md +34 -8
- package/templates/hooks/_resolve-ctxr.sh +37 -0
- package/templates/hooks/claude-code-write-gate.sh +34 -6
- package/templates/hooks/pre-commit.sh +15 -8
- package/templates/serve/shell.html +16 -2
- package/templates/serve/style.css +145 -3
- package/templates/skills/ctxr-connection-finding.md +7 -5
- package/templates/skills/ctxr-ingest-orchestration.md +15 -9
- package/templates/skills/ctxr-publish.md +7 -8
- package/templates/skills/ctxr-session-lifecycle.md +20 -0
- package/templates/skills/ctxr-upgrade.md +44 -0
- package/dist/commands/migrate.d.ts +0 -30
- package/dist/commands/migrate.d.ts.map +0 -1
- package/dist/commands/migrate.js +0 -56
- package/dist/commands/migrate.js.map +0 -1
- package/dist/core/migrations/add-explanation-craft-skill.d.ts +0 -26
- package/dist/core/migrations/add-explanation-craft-skill.d.ts.map +0 -1
- package/dist/core/migrations/add-explanation-craft-skill.js +0 -94
- package/dist/core/migrations/add-explanation-craft-skill.js.map +0 -1
- package/dist/core/migrations/archive-destination-from-taxonomy.d.ts +0 -35
- package/dist/core/migrations/archive-destination-from-taxonomy.d.ts.map +0 -1
- package/dist/core/migrations/archive-destination-from-taxonomy.js +0 -109
- package/dist/core/migrations/archive-destination-from-taxonomy.js.map +0 -1
- package/dist/core/migrations/drop-access-axes.d.ts +0 -24
- package/dist/core/migrations/drop-access-axes.d.ts.map +0 -1
- package/dist/core/migrations/drop-access-axes.js +0 -54
- package/dist/core/migrations/drop-access-axes.js.map +0 -1
- package/dist/core/migrations/drop-forge-and-workspaces-external.d.ts +0 -19
- package/dist/core/migrations/drop-forge-and-workspaces-external.d.ts.map +0 -1
- package/dist/core/migrations/drop-forge-and-workspaces-external.js +0 -49
- package/dist/core/migrations/drop-forge-and-workspaces-external.js.map +0 -1
- package/dist/core/migrations/registry.d.ts +0 -16
- package/dist/core/migrations/registry.d.ts.map +0 -1
- package/dist/core/migrations/registry.js +0 -30
- package/dist/core/migrations/registry.js.map +0 -1
- package/dist/core/migrations/rename-conventions-path.d.ts +0 -26
- package/dist/core/migrations/rename-conventions-path.d.ts.map +0 -1
- package/dist/core/migrations/rename-conventions-path.js +0 -86
- package/dist/core/migrations/rename-conventions-path.js.map +0 -1
- package/dist/core/migrations/rename-procedures-path.d.ts +0 -17
- package/dist/core/migrations/rename-procedures-path.d.ts.map +0 -1
- package/dist/core/migrations/rename-procedures-path.js +0 -45
- package/dist/core/migrations/rename-procedures-path.js.map +0 -1
- package/dist/core/migrations/types.d.ts +0 -27
- package/dist/core/migrations/types.d.ts.map +0 -1
- package/dist/core/migrations/types.js +0 -2
- 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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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
|
|
5
|
-
|
|
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
|
|
11
|
-
|
|
12
|
-
`ctxr source add-alt <path> --id <new-id>` on the existing
|
|
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
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
3
|
-
|
|
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
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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"}
|
package/dist/commands/migrate.js
DELETED
|
@@ -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"}
|