ctxr-cli 0.8.0 → 0.9.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 +303 -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 +21 -5
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/source-check.d.ts.map +1 -1
- package/dist/commands/source-check.js +27 -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/config/defaults.d.ts +103 -4
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +76 -4
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/render.d.ts +11 -0
- package/dist/config/render.d.ts.map +1 -1
- package/dist/config/render.js +85 -3
- package/dist/config/render.js.map +1 -1
- package/dist/config/schema.d.ts +50 -30
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +151 -62
- 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/checks/harness-portability-checks.d.ts +1 -1
- package/dist/core/checks/harness-portability-checks.d.ts.map +1 -1
- package/dist/core/checks/harness-portability-checks.js +2 -3
- package/dist/core/checks/harness-portability-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/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/errors.d.ts +19 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +53 -1
- 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/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/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/migrations/config-defaults-as-the-convention.d.ts +21 -0
- package/dist/core/migrations/config-defaults-as-the-convention.d.ts.map +1 -0
- package/dist/core/migrations/config-defaults-as-the-convention.js +54 -0
- package/dist/core/migrations/config-defaults-as-the-convention.js.map +1 -0
- package/dist/core/migrations/registry.d.ts.map +1 -1
- package/dist/core/migrations/registry.js +4 -0
- package/dist/core/migrations/registry.js.map +1 -1
- package/dist/core/migrations/retain-captures-as-provenance.d.ts +22 -0
- package/dist/core/migrations/retain-captures-as-provenance.d.ts.map +1 -0
- package/dist/core/migrations/retain-captures-as-provenance.js +133 -0
- package/dist/core/migrations/retain-captures-as-provenance.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/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/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/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 +0 -5
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +38 -3
- package/dist/run.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +12 -4
- 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/skills/ctxr-connection-finding.md +7 -5
- package/templates/skills/ctxr-ingest-orchestration.md +15 -9
- package/templates/skills/ctxr-publish.md +7 -8
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
## Capturing and ingesting new material
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Captures live under `__CAPTURE_ROOT__`, which is excluded from retrieval: nothing in it is a note, and
|
|
4
|
+
nothing in it is returned by a search, listed in the catalog, or drawn in the graph. It is tracked in git
|
|
5
|
+
all the same — a capture is the provenance behind a note, not scratch space.
|
|
6
|
+
|
|
7
|
+
To capture something new, write the material into `__INBOX_PATH__` — no CLI command wraps this. It may
|
|
8
|
+
already carry these two fields, since whatever fetched it usually knows them:
|
|
6
9
|
|
|
7
10
|
- `source_type`
|
|
8
11
|
- `source_id`
|
|
12
|
+
|
|
13
|
+
It MUST NOT carry either of these; contexture assigns them once, at ingest, and never before:
|
|
14
|
+
|
|
9
15
|
- `source_hash`
|
|
10
16
|
- `ingested`
|
|
11
17
|
|
|
12
|
-
Before ingesting, run `ctxr source check <path> --source-id <id>` to get one of
|
|
13
|
-
`
|
|
14
|
-
resolve the ambiguity yourself rather than guessing which
|
|
18
|
+
Before ingesting, run `ctxr source check <path> --source-id <id>` to get one of five verdicts: `new`,
|
|
19
|
+
`already_ingested`, `drift` (same identity, the source's content moved), `alternate_source_match`, or
|
|
20
|
+
`multiple_matches` — the last one means stop and resolve the ambiguity yourself rather than guessing which
|
|
21
|
+
existing record it is.
|
|
22
|
+
|
|
23
|
+
Then write, or extend, the note this material informed. Ingest does not create it: deciding what the store
|
|
24
|
+
should know is the work, and "a new note" is only one of the answers.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
ctxr ingest <path> --into <note> --source-type <type> --source-id <id>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
That stamps the four fields onto the capture, moves it out of the inbox into `__CAPTURE_ROOT__` under the
|
|
31
|
+
month it was ingested, and records its path in the note's `sources` list. The note itself carries no source
|
|
32
|
+
identity — it is free to be rewritten, merged, or restructured without ever invalidating the frozen hash.
|
|
33
|
+
A note may cite as many captures as it was built from.
|
|
15
34
|
|
|
16
|
-
|
|
17
|
-
|
|
35
|
+
Material that is not markdown cannot carry frontmatter, so it travels with a markdown sidecar beside it
|
|
36
|
+
naming the file in `capture_file`. The hash is taken over that file's bytes, and the two move together.
|
|
@@ -1,14 +1,40 @@
|
|
|
1
|
-
## Retrieval:
|
|
1
|
+
## Retrieval: one pass, three steps
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Retrieval is a single pass — **enter**, **expand**, **widen** — not three tools to choose between.
|
|
4
|
+
contexture builds and maintains the first two ahead of time; the third is yours.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
- **Graph** (`ctxr graph query ...`): the wikilink graph between notes — neighbors, shortest path, hubs, orphans, clusters, bridges; `--type <relation>` follows one configured relation.
|
|
7
|
-
- **Graph document** (`__GRAPH_DOCUMENT_PATH__`, rebuilt by `ctxr graph build`): hub notes by cluster, cross-cluster bridges, and orphans — read it for cluster context before writing.
|
|
6
|
+
**1. Enter.** Name where to start, positionally or relationally:
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
- `--section <id>` — every note a catalog section lists (`ctxr catalog show --section <id>` reads one directly)
|
|
9
|
+
- `--under <prefix>` — every retrievable note under a path prefix
|
|
10
|
+
- `--seed <path>` — a note you already hold, including one your own search just found
|
|
11
|
+
- `--entity <name>` — every note linking to a concept
|
|
12
|
+
|
|
13
|
+
**2. Expand.** `ctxr context gather` takes those selectors and walks the wikilink graph out from them,
|
|
14
|
+
returning each reachable note with its catalog gloss, its hop distance, and labels saying why it is
|
|
15
|
+
there — so you can triage the set without opening a single file, then read only what the glosses
|
|
16
|
+
justify:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
ctxr context gather --section <id> --hops 1
|
|
20
|
+
ctxr context gather --seed <path> --hops 2 --type <relation>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Results are ordered: live material before demoted (archived) material, nearer hops before farther,
|
|
24
|
+
then by how the note was reached, then by path. `no_gloss` on a result means the catalog has no
|
|
25
|
+
description for that note yet — the pass found it structurally, not by what it says.
|
|
26
|
+
|
|
27
|
+
For structure on its own — shortest path, hubs, orphans, clusters, bridges — query the graph directly
|
|
28
|
+
with `ctxr graph query ...`, and read the graph document at `__GRAPH_DOCUMENT_PATH__` (rebuilt by
|
|
29
|
+
`ctxr graph build`) for cluster context before writing.
|
|
30
|
+
|
|
31
|
+
**3. Widen.** For a literal or entity question the first two steps do not answer — a specific string,
|
|
32
|
+
an exact identifier, a phrase — use your own content-matching tool (e.g. grep/ripgrep) against the
|
|
33
|
+
store, scoped to exclude:
|
|
11
34
|
|
|
12
35
|
__EXCLUSION_PATHS__
|
|
13
36
|
|
|
14
|
-
|
|
37
|
+
Feed anything it finds back in as `--seed` to pick the pass up again from there.
|
|
38
|
+
|
|
39
|
+
There is no `ctxr search` command. Nothing here takes a free-text query, and no result carries a
|
|
40
|
+
relevance score. Ranked or semantic search is deferred to a future version — do not look for one.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# --- shared: resolve the ctxr CLI ------------------------------------------
|
|
2
|
+
# Authored in templates/hooks/_resolve-ctxr.sh and inlined verbatim into every
|
|
3
|
+
# hook that needs it at render time (src/core/hooks.ts) — one copy of a
|
|
4
|
+
# security decision, never two that can drift apart. Do not edit the inlined
|
|
5
|
+
# copy; re-run `ctxr init` / `ctxr update` to regenerate it.
|
|
6
|
+
#
|
|
7
|
+
# Resolves at RUN time, so the rendered hook is byte-identical in every
|
|
8
|
+
# checkout of this store: a path baked in when the file was generated is
|
|
9
|
+
# valid only on the machine that generated it, and this file is committed.
|
|
10
|
+
#
|
|
11
|
+
# Order: $CONTEXTURE_BIN, then `ctxr` on PATH. Nothing else is consulted, and
|
|
12
|
+
# there is no "give up and continue" branch — when neither resolves, this
|
|
13
|
+
# calls ctxr_unavailable <reason>, which each hook defines above and which
|
|
14
|
+
# must not return. A CONTEXTURE_BIN that is set but broken is terminal: it is
|
|
15
|
+
# a deliberate pin, and silently running a different binary instead would
|
|
16
|
+
# defeat the operator who set it.
|
|
17
|
+
#
|
|
18
|
+
# Leaves the resolved command in the positional parameters ("$@"). Neither
|
|
19
|
+
# hook that inlines this reads its own arguments.
|
|
20
|
+
if [ -n "${CONTEXTURE_BIN:-}" ]; then
|
|
21
|
+
if [ ! -f "$CONTEXTURE_BIN" ]; then
|
|
22
|
+
ctxr_unavailable "CONTEXTURE_BIN names a path that is not a file: $CONTEXTURE_BIN"
|
|
23
|
+
elif [ -x "$CONTEXTURE_BIN" ]; then
|
|
24
|
+
set -- "$CONTEXTURE_BIN"
|
|
25
|
+
elif command -v node >/dev/null 2>&1; then
|
|
26
|
+
# A plain dist/bin.js: tsc emits it non-executable, and only npm's
|
|
27
|
+
# bin-linking sets the bit, so a dev checkout needs node to run it.
|
|
28
|
+
set -- node "$CONTEXTURE_BIN"
|
|
29
|
+
else
|
|
30
|
+
ctxr_unavailable "CONTEXTURE_BIN is not executable and no node is on PATH to run it: $CONTEXTURE_BIN"
|
|
31
|
+
fi
|
|
32
|
+
elif command -v ctxr >/dev/null 2>&1; then
|
|
33
|
+
set -- ctxr
|
|
34
|
+
else
|
|
35
|
+
ctxr_unavailable "no ctxr on PATH, and CONTEXTURE_BIN is not set"
|
|
36
|
+
fi
|
|
37
|
+
# --- end shared: resolve the ctxr CLI --------------------------------------
|
|
@@ -3,13 +3,41 @@
|
|
|
3
3
|
# controlled — do not edit by hand; re-run to regenerate. A PreToolUse hook:
|
|
4
4
|
# relays the tool-call envelope on stdin to `ctxr adapters write-gate`, which
|
|
5
5
|
# decides whether to deny it, and relays its stdout and exit code unchanged.
|
|
6
|
+
# Carries no path specific to the machine that generated it — `ctxr` is
|
|
7
|
+
# resolved at run time, and an edit this gate could not evaluate is denied,
|
|
8
|
+
# not allowed unchecked.
|
|
6
9
|
set -eu
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
# The write gate is an enforcement primitive, and a gate that cannot run is
|
|
12
|
+
# not a passing decision (adapters spec). This speaks the same PreToolUse deny
|
|
13
|
+
# protocol `ctxr adapters write-gate` does — a JSON body on stdout, exit 0 —
|
|
14
|
+
# because that is the only vocabulary the harness reads as "denied, and here
|
|
15
|
+
# is why". A nonzero exit other than 2 is reported as a hook error and the
|
|
16
|
+
# edit proceeds, which is the failure this replaces; exit 2 hard-blocks
|
|
17
|
+
# regardless of output and would conflate a broken install with a decision.
|
|
18
|
+
ctxr_unavailable() {
|
|
19
|
+
# Drain the envelope the harness is writing to us before exiting: the
|
|
20
|
+
# normal path reads stdin to EOF via `ctxr adapters write-gate`, and a
|
|
21
|
+
# harness that writes the full envelope before checking our exit code
|
|
22
|
+
# would otherwise see its own write fail (EPIPE/SIGPIPE) once we exit
|
|
23
|
+
# without ever reading it.
|
|
24
|
+
cat >/dev/null 2>&1 || true
|
|
25
|
+
printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"contexture: the write gate could not run (%s), so this edit is denied rather than allowed unchecked. Install the CLI (npm install -g ctxr-cli) or set CONTEXTURE_BIN to its dist/bin.js, then retry."}}\n' "$1"
|
|
12
26
|
exit 0
|
|
13
|
-
|
|
27
|
+
}
|
|
14
28
|
|
|
15
|
-
|
|
29
|
+
__RESOLVE_CTXR__
|
|
30
|
+
|
|
31
|
+
# Not `exec`: a resolved command can still fail to execute (a broken symlink,
|
|
32
|
+
# a non-executable file found on PATH), and exec's 126/127 would reach the
|
|
33
|
+
# harness as an ordinary hook error — fail-open, the bug this file exists to
|
|
34
|
+
# close. Every other exit code and all of stdout are relayed unchanged, so the
|
|
35
|
+
# gate's own deliberate "I could not decide, apply normal permission flow"
|
|
36
|
+
# exits (never 2) keep their documented meaning.
|
|
37
|
+
status=0
|
|
38
|
+
out=$("$@" adapters write-gate) || status=$?
|
|
39
|
+
if [ "$status" -eq 126 ] || [ "$status" -eq 127 ]; then
|
|
40
|
+
ctxr_unavailable "the resolved ctxr could not be executed (exit $status)"
|
|
41
|
+
fi
|
|
42
|
+
printf '%s' "$out"
|
|
43
|
+
exit "$status"
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# Installed by `ctxr init` (write-lifecycle spec). Version-controlled —
|
|
3
3
|
# do not edit by hand; re-run `ctxr init` or `ctxr doctor` to
|
|
4
|
-
# regenerate. Runs `doctor --staged`
|
|
5
|
-
#
|
|
4
|
+
# regenerate. Runs `doctor --staged` with the ctxr this machine resolves at
|
|
5
|
+
# run time, and refuses the commit if it finds a real problem — or if it
|
|
6
|
+
# could not run that validation at all.
|
|
6
7
|
set -eu
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
# A commit this hook could not check is refused, not passed: the point of the
|
|
10
|
+
# hook is that no unvalidated change is committed, and "ctxr is not installed
|
|
11
|
+
# here" is not evidence that the staged diff is clean.
|
|
12
|
+
ctxr_unavailable() {
|
|
13
|
+
echo "ctxr: commit refused — $1" >&2
|
|
14
|
+
echo "ctxr: this hook validates staged changes with 'ctxr doctor --staged', and will not pass a commit it could not check." >&2
|
|
15
|
+
echo "ctxr: install the CLI with 'npm install -g ctxr-cli', or set CONTEXTURE_BIN to its dist/bin.js." >&2
|
|
16
|
+
echo "ctxr: 'git commit --no-verify' bypasses this hook if you must commit before repairing the install." >&2
|
|
17
|
+
exit 1
|
|
18
|
+
}
|
|
9
19
|
|
|
10
|
-
|
|
11
|
-
echo "ctxr: warning — could not find $CONTEXTURE_BIN; skipping pre-commit validation." >&2
|
|
12
|
-
exit 0
|
|
13
|
-
fi
|
|
20
|
+
__RESOLVE_CTXR__
|
|
14
21
|
|
|
15
|
-
if ! output=$(
|
|
22
|
+
if ! output=$("$@" doctor --staged --json 2>&1); then
|
|
16
23
|
echo "$output" >&2
|
|
17
24
|
echo "ctxr: commit refused — staged changes failed 'doctor --staged'." >&2
|
|
18
25
|
exit 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
|
|