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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { RunEnv } from './env.js';
|
|
2
|
+
import type { Finding } from './envelope.js';
|
|
3
|
+
import type { Store } from './store.js';
|
|
4
|
+
/**
|
|
5
|
+
* The release comparison behind `ctxr version --check` and the session-start /
|
|
6
|
+
* update advisory (cli-contract: an explicit release check reports its answer
|
|
7
|
+
* through the exit code).
|
|
8
|
+
*
|
|
9
|
+
* Hand-rolled over the plain three-part shape rather than taking a semver
|
|
10
|
+
* dependency (design.md D7): every published release is X.Y.Z with no
|
|
11
|
+
* prerelease or build metadata, and a comparison that handles exactly that and
|
|
12
|
+
* REFUSES anything else fails in the right direction. An unrecognized version
|
|
13
|
+
* is reported as undeterminable and named — the fail-loud contract applied to
|
|
14
|
+
* parsing — never compared by guesswork, and never quietly treated as "current".
|
|
15
|
+
*/
|
|
16
|
+
export type ReleaseComparison = {
|
|
17
|
+
readonly kind: 'current';
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'newer-available';
|
|
20
|
+
readonly installed: string;
|
|
21
|
+
readonly latest: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: 'undetermined';
|
|
24
|
+
readonly reason: string;
|
|
25
|
+
};
|
|
26
|
+
/** Parses a plain X.Y.Z version. Returns undefined for anything else — including
|
|
27
|
+
* a prerelease, build metadata, a `v` prefix, or a leading/trailing space. */
|
|
28
|
+
export declare function parseVersion(version: string): [number, number, number] | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* An installed version AHEAD of the published one is 'current', not an error:
|
|
31
|
+
* that is exactly what a maintainer running an unreleased build sees, and it
|
|
32
|
+
* is not a condition to nag them about.
|
|
33
|
+
*/
|
|
34
|
+
export declare function compareRelease(installed: string, latest: string): ReleaseComparison;
|
|
35
|
+
/**
|
|
36
|
+
* Store-local, under the derived-cache subpath that is already gitignored and
|
|
37
|
+
* already declared in `derived.paths` — so it needs no new plumbing and never
|
|
38
|
+
* rides review. Deliberately NOT ~/.cache: that would be the first thing this
|
|
39
|
+
* codebase writes outside a store root, and under the integration tests'
|
|
40
|
+
* hermetic HOME it would write to a nonexistent path and silently do nothing
|
|
41
|
+
* (design.md D6).
|
|
42
|
+
*/
|
|
43
|
+
export declare function updateCheckCachePath(store: Store): string;
|
|
44
|
+
/** The environment variable that suppresses the check for one invocation. */
|
|
45
|
+
export declare const UPDATE_CHECK_ENV_VAR = "CONTEXTURE_UPDATE_CHECK";
|
|
46
|
+
export interface UpdateAdvisory {
|
|
47
|
+
findings: Finding[];
|
|
48
|
+
/** The stderr line, when there is one to print. */
|
|
49
|
+
notice?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* cli-contract: an advisory about a newer release never changes the outcome of
|
|
53
|
+
* the command carrying it.
|
|
54
|
+
*
|
|
55
|
+
* This function has NO throwing path, and that is a requirement rather than an
|
|
56
|
+
* intention (design.md D5). Session start creates a git worktree BEFORE this
|
|
57
|
+
* runs, and runCommand maps any escaping error to the internal-error code — so
|
|
58
|
+
* an unhandled rejection here would report a failed session that had in fact
|
|
59
|
+
* succeeded, leaving an orphan worktree behind. Every failure below becomes a
|
|
60
|
+
* finding.
|
|
61
|
+
*/
|
|
62
|
+
export declare function updateAdvisory(env: RunEnv, store: Store): Promise<UpdateAdvisory>;
|
|
63
|
+
//# sourceMappingURL=version-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.d.ts","sourceRoot":"","sources":["../../src/core/version-check.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAI/D;+EAC+E;AAC/E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAQlF;AAWD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAanF;AAQD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEzD;AAED,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AA0D9D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiBD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,CAoCvF"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { SHIPPED_DEFAULTS } from '../config/defaults.js';
|
|
4
|
+
import { writeFileAtomic } from './fs/atomic.js';
|
|
5
|
+
import { ownPackageName } from './registry.js';
|
|
6
|
+
import { CLI_VERSION } from '../version.js';
|
|
7
|
+
const THREE_PART = /^(\d+)\.(\d+)\.(\d+)$/;
|
|
8
|
+
/** Parses a plain X.Y.Z version. Returns undefined for anything else — including
|
|
9
|
+
* a prerelease, build metadata, a `v` prefix, or a leading/trailing space. */
|
|
10
|
+
export function parseVersion(version) {
|
|
11
|
+
const match = THREE_PART.exec(version);
|
|
12
|
+
if (!match)
|
|
13
|
+
return undefined;
|
|
14
|
+
const parts = [match[1], match[2], match[3]].map((part) => Number(part));
|
|
15
|
+
// Number() on a digits-only string cannot be NaN, but it can exceed the safe
|
|
16
|
+
// integer range on absurd input; refuse rather than compare imprecisely.
|
|
17
|
+
if (parts.some((part) => !Number.isSafeInteger(part)))
|
|
18
|
+
return undefined;
|
|
19
|
+
return [parts[0], parts[1], parts[2]];
|
|
20
|
+
}
|
|
21
|
+
/** Numeric, component-wise. Returns a negative number when `a` precedes `b`. */
|
|
22
|
+
function compareParsed(a, b) {
|
|
23
|
+
for (let i = 0; i < 3; i += 1) {
|
|
24
|
+
const diff = a[i] - b[i];
|
|
25
|
+
if (diff !== 0)
|
|
26
|
+
return diff;
|
|
27
|
+
}
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* An installed version AHEAD of the published one is 'current', not an error:
|
|
32
|
+
* that is exactly what a maintainer running an unreleased build sees, and it
|
|
33
|
+
* is not a condition to nag them about.
|
|
34
|
+
*/
|
|
35
|
+
export function compareRelease(installed, latest) {
|
|
36
|
+
const installedParts = parseVersion(installed);
|
|
37
|
+
if (!installedParts) {
|
|
38
|
+
return { kind: 'undetermined', reason: `the installed version "${installed}" is not a X.Y.Z version` };
|
|
39
|
+
}
|
|
40
|
+
const latestParts = parseVersion(latest);
|
|
41
|
+
if (!latestParts) {
|
|
42
|
+
return { kind: 'undetermined', reason: `the published version "${latest}" is not a X.Y.Z version` };
|
|
43
|
+
}
|
|
44
|
+
if (compareParsed(installedParts, latestParts) < 0) {
|
|
45
|
+
return { kind: 'newer-available', installed, latest };
|
|
46
|
+
}
|
|
47
|
+
return { kind: 'current' };
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// The advisory: the cached, never-throwing path used by session start and
|
|
51
|
+
// update. `ctxr version --check` deliberately does NOT come through here — an
|
|
52
|
+
// operator asking explicitly is asking about now, not about the last answer.
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
/**
|
|
55
|
+
* Store-local, under the derived-cache subpath that is already gitignored and
|
|
56
|
+
* already declared in `derived.paths` — so it needs no new plumbing and never
|
|
57
|
+
* rides review. Deliberately NOT ~/.cache: that would be the first thing this
|
|
58
|
+
* codebase writes outside a store root, and under the integration tests'
|
|
59
|
+
* hermetic HOME it would write to a nonexistent path and silently do nothing
|
|
60
|
+
* (design.md D6).
|
|
61
|
+
*/
|
|
62
|
+
export function updateCheckCachePath(store) {
|
|
63
|
+
return path.join(store.root, '.contexture', 'cache', 'update-check.json');
|
|
64
|
+
}
|
|
65
|
+
/** The environment variable that suppresses the check for one invocation. */
|
|
66
|
+
export const UPDATE_CHECK_ENV_VAR = 'CONTEXTURE_UPDATE_CHECK';
|
|
67
|
+
function isFresh(entry, now, ttlHours) {
|
|
68
|
+
const checkedAt = Date.parse(entry.checked_at);
|
|
69
|
+
if (!Number.isFinite(checkedAt))
|
|
70
|
+
return false;
|
|
71
|
+
const ageMs = now.getTime() - checkedAt;
|
|
72
|
+
// A cache stamped in the future is not fresh — a clock that moved backwards
|
|
73
|
+
// must not pin the answer forever.
|
|
74
|
+
return ageMs >= 0 && ageMs < ttlHours * 60 * 60 * 1000;
|
|
75
|
+
}
|
|
76
|
+
async function readCache(store, now, ttlHours) {
|
|
77
|
+
try {
|
|
78
|
+
const raw = await readFile(updateCheckCachePath(store), 'utf8');
|
|
79
|
+
const entry = JSON.parse(raw);
|
|
80
|
+
if (typeof entry.latest !== 'string' || typeof entry.checked_at !== 'string')
|
|
81
|
+
return undefined;
|
|
82
|
+
return isFresh(entry, now, ttlHours) ? entry.latest : undefined;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Missing, unreadable, or corrupt are all a miss — never an error. The
|
|
86
|
+
// cache is an optimization; failing on it would let a stray byte on disk
|
|
87
|
+
// fail a session.
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function writeCache(store, now, latest) {
|
|
92
|
+
try {
|
|
93
|
+
const filePath = updateCheckCachePath(store);
|
|
94
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
95
|
+
const entry = { checked_at: now.toISOString(), latest };
|
|
96
|
+
await writeFileAtomic(filePath, `${JSON.stringify(entry, null, 2)}\n`);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// An unwritable cache costs one extra request next time. It is not a
|
|
100
|
+
// reason to fail the command that was carrying the advisory.
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Reads the effective settings, falling back to the shipped defaults for a config that predates the block. */
|
|
104
|
+
function updateCheckSettings(store) {
|
|
105
|
+
const configured = store.config.update_check;
|
|
106
|
+
return {
|
|
107
|
+
enabled: configured?.enabled ?? SHIPPED_DEFAULTS.update_check.enabled,
|
|
108
|
+
ttlHours: configured?.ttl_hours ?? SHIPPED_DEFAULTS.update_check.ttl_hours,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** Any explicit falsey spelling turns the check off for this invocation. */
|
|
112
|
+
function suppressedByEnv(env) {
|
|
113
|
+
const raw = env.env[UPDATE_CHECK_ENV_VAR];
|
|
114
|
+
if (raw === undefined)
|
|
115
|
+
return false;
|
|
116
|
+
return ['0', 'false', 'no', 'off', ''].includes(raw.trim().toLowerCase());
|
|
117
|
+
}
|
|
118
|
+
const NO_ADVISORY = { findings: [] };
|
|
119
|
+
function checkFailed(reason) {
|
|
120
|
+
return {
|
|
121
|
+
findings: [
|
|
122
|
+
{
|
|
123
|
+
code: 'cli.update_check_failed',
|
|
124
|
+
severity: 'info',
|
|
125
|
+
message: `the release check could not be completed: ${reason}`,
|
|
126
|
+
subject: ownPackageName(),
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* cli-contract: an advisory about a newer release never changes the outcome of
|
|
133
|
+
* the command carrying it.
|
|
134
|
+
*
|
|
135
|
+
* This function has NO throwing path, and that is a requirement rather than an
|
|
136
|
+
* intention (design.md D5). Session start creates a git worktree BEFORE this
|
|
137
|
+
* runs, and runCommand maps any escaping error to the internal-error code — so
|
|
138
|
+
* an unhandled rejection here would report a failed session that had in fact
|
|
139
|
+
* succeeded, leaving an orphan worktree behind. Every failure below becomes a
|
|
140
|
+
* finding.
|
|
141
|
+
*/
|
|
142
|
+
export async function updateAdvisory(env, store) {
|
|
143
|
+
try {
|
|
144
|
+
const { enabled, ttlHours } = updateCheckSettings(store);
|
|
145
|
+
if (!enabled || suppressedByEnv(env))
|
|
146
|
+
return NO_ADVISORY;
|
|
147
|
+
const now = env.now();
|
|
148
|
+
let latest = await readCache(store, now, ttlHours);
|
|
149
|
+
if (latest === undefined) {
|
|
150
|
+
const lookup = await env.registry.latestVersion(ownPackageName());
|
|
151
|
+
if (lookup.kind === 'undetermined')
|
|
152
|
+
return checkFailed(lookup.reason);
|
|
153
|
+
latest = lookup.version;
|
|
154
|
+
await writeCache(store, now, latest);
|
|
155
|
+
}
|
|
156
|
+
const comparison = compareRelease(CLI_VERSION, latest);
|
|
157
|
+
if (comparison.kind === 'undetermined')
|
|
158
|
+
return checkFailed(comparison.reason);
|
|
159
|
+
if (comparison.kind === 'current')
|
|
160
|
+
return NO_ADVISORY;
|
|
161
|
+
const message = `ctxr ${comparison.installed} is installed; ${comparison.latest} is available.`;
|
|
162
|
+
return {
|
|
163
|
+
findings: [
|
|
164
|
+
{
|
|
165
|
+
code: 'cli.update_available',
|
|
166
|
+
severity: 'info',
|
|
167
|
+
message,
|
|
168
|
+
subject: ownPackageName(),
|
|
169
|
+
details: { installed: comparison.installed, latest: comparison.latest },
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
notice: `${message} Run the ctxr-upgrade skill to upgrade.`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
// The backstop for anything the branches above did not anticipate. Reaching
|
|
177
|
+
// it is a bug, but reaching it must still not fail the caller's command.
|
|
178
|
+
return checkFailed(err instanceof Error ? err.message : String(err));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/core/version-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,8 +13,8 @@ export interface PathGateResult {
|
|
|
13
13
|
* directory's symlinks are followed. The sanctioned-location rule is
|
|
14
14
|
* opt-in — with `write_lifecycle.writable_paths` empty (the default),
|
|
15
15
|
* every in-store path is accepted; once any path is declared, only a
|
|
16
|
-
* configured taxonomy layer, the
|
|
17
|
-
* contexture-owned location passes.
|
|
16
|
+
* configured taxonomy layer, the capture tier, a declared writable path, or
|
|
17
|
+
* a contexture-owned location passes.
|
|
18
18
|
*/
|
|
19
19
|
export declare function sanctionedPath(config: StoreConfig, root: string, relativePath: string): Promise<PathGateResult>;
|
|
20
20
|
export interface WriteScopeResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-gate.d.ts","sourceRoot":"","sources":["../../../src/core/write-lifecycle/path-gate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"path-gate.d.ts","sourceRoot":"","sources":["../../../src/core/write-lifecycle/path-gate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAmFD;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAsBrH;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAqBvH"}
|
|
@@ -2,6 +2,7 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import { realpath } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { configuredAdapters } from '../../adapters/registry.js';
|
|
5
|
+
import { isUnderAnyPrefix } from '../fs/prefix.js';
|
|
5
6
|
import { isLinkedWorktreeRoot } from '../git/repo.js';
|
|
6
7
|
function normalizePrefix(prefix) {
|
|
7
8
|
return prefix.replace(/\/+$/, '');
|
|
@@ -33,12 +34,6 @@ async function resolveStorePath(root, relativePath) {
|
|
|
33
34
|
}
|
|
34
35
|
return { kind: 'inside', rel };
|
|
35
36
|
}
|
|
36
|
-
function isUnderAnyPrefix(relativePath, prefixes) {
|
|
37
|
-
return prefixes.some((prefix) => {
|
|
38
|
-
const trimmed = normalizePrefix(prefix);
|
|
39
|
-
return relativePath === trimmed || relativePath.startsWith(`${trimmed}/`);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
37
|
/**
|
|
43
38
|
* session-capture-command spec (D5): locations contexture itself owns are
|
|
44
39
|
* always sanctioned, regardless of writable_paths.
|
|
@@ -67,7 +62,11 @@ function contextureOwnedPrefixes(config) {
|
|
|
67
62
|
function sanctionedPrefixesFor(config) {
|
|
68
63
|
return [
|
|
69
64
|
...config.taxonomy.layers.map((layer) => layer.path),
|
|
70
|
-
|
|
65
|
+
// retain-captures-as-provenance: the capture ROOT, not the inbox inside
|
|
66
|
+
// it — ingest's own write moves a capture out of the inbox and into the
|
|
67
|
+
// tier's dated directory, which a store declaring writable_paths would
|
|
68
|
+
// otherwise refuse.
|
|
69
|
+
config.ingest.capture_root,
|
|
71
70
|
...config.write_lifecycle.writable_paths,
|
|
72
71
|
...contextureOwnedPrefixes(config),
|
|
73
72
|
];
|
|
@@ -82,8 +81,8 @@ function sanctionedPrefixesFor(config) {
|
|
|
82
81
|
* directory's symlinks are followed. The sanctioned-location rule is
|
|
83
82
|
* opt-in — with `write_lifecycle.writable_paths` empty (the default),
|
|
84
83
|
* every in-store path is accepted; once any path is declared, only a
|
|
85
|
-
* configured taxonomy layer, the
|
|
86
|
-
* contexture-owned location passes.
|
|
84
|
+
* configured taxonomy layer, the capture tier, a declared writable path, or
|
|
85
|
+
* a contexture-owned location passes.
|
|
87
86
|
*/
|
|
88
87
|
export async function sanctionedPath(config, root, relativePath) {
|
|
89
88
|
const resolution = await resolveStorePath(root, relativePath);
|
|
@@ -100,7 +99,7 @@ export async function sanctionedPath(config, root, relativePath) {
|
|
|
100
99
|
if (!isUnderAnyPrefix(rel, sanctionedPrefixesFor(config))) {
|
|
101
100
|
return {
|
|
102
101
|
ok: false,
|
|
103
|
-
reason: 'is not under a configured taxonomy layer, the
|
|
102
|
+
reason: 'is not under a configured taxonomy layer, the capture tier, a declared writable path, or a contexture-owned location',
|
|
104
103
|
};
|
|
105
104
|
}
|
|
106
105
|
return { ok: true };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-gate.js","sourceRoot":"","sources":["../../../src/core/write-lifecycle/path-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAOtD,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAaD,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,YAAoB;IAChE,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5E,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IACnC,CAAC;IAED,+FAA+F;IAC/F,gGAAgG;IAChG,iEAAiE;IACjE,IAAI,QAAQ,GAAG,MAAM,CAAC;IACtB,OAAO,QAAQ,KAAK,cAAc,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,MAAM,KAAK,QAAQ;YAAE,MAAM;QAC/B,QAAQ,GAAG,MAAM,CAAC;IACpB,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;QAC5E,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAClG,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AACjC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"path-gate.js","sourceRoot":"","sources":["../../../src/core/write-lifecycle/path-gate.ts"],"names":[],"mappings":"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"}
|
package/dist/run.d.ts
CHANGED
|
@@ -6,11 +6,6 @@ import { ExitCode } from './core/exit-codes.js';
|
|
|
6
6
|
* automatically gets json-envelope-conformance coverage the moment it's
|
|
7
7
|
* added here.
|
|
8
8
|
*/
|
|
9
|
-
export declare const COMMAND_NAMES: readonly ['init', 'doctor'];
|
|
10
|
-
/**
|
|
11
|
-
* The one testable seam for the whole CLI: given argv and an injected
|
|
12
|
-
* RunEnv, returns the exit code it would have produced — no process-global
|
|
13
|
-
* mutation, no real subprocess required for a unit test.
|
|
14
|
-
*/
|
|
9
|
+
export declare const COMMAND_NAMES: readonly ['init', 'doctor', 'version'];
|
|
15
10
|
export declare function run(argv: readonly string[], env: RunEnv): Promise<ExitCode>;
|
|
16
11
|
//# sourceMappingURL=run.d.ts.map
|
package/dist/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQhD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,YAAI,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAC;AA+GpE,wBAAsB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAghBjF"}
|
package/dist/run.js
CHANGED
|
@@ -8,7 +8,7 @@ import * as archiveCommand from './commands/archive.js';
|
|
|
8
8
|
import * as doctorCommand from './commands/doctor.js';
|
|
9
9
|
import * as ingestCommand from './commands/ingest.js';
|
|
10
10
|
import * as lintCommand from './commands/lint.js';
|
|
11
|
-
import * as
|
|
11
|
+
import * as contextGatherCommand from './commands/context-gather.js';
|
|
12
12
|
import * as graphBuildCommand from './commands/graph-build.js';
|
|
13
13
|
import * as entryAppendCommand from './commands/entry-append.js';
|
|
14
14
|
import * as graphQueryCommand from './commands/graph-query.js';
|
|
@@ -34,6 +34,7 @@ import { createReporter } from './core/reporter.js';
|
|
|
34
34
|
import { openStore } from './core/store.js';
|
|
35
35
|
import * as updateCommand from './commands/update.js';
|
|
36
36
|
import * as verifyCommand from './commands/verify.js';
|
|
37
|
+
import * as versionCommand from './commands/version.js';
|
|
37
38
|
import { CLI_VERSION } from './version.js';
|
|
38
39
|
/**
|
|
39
40
|
* Every registered top-level command name (excluding subcommand groups like
|
|
@@ -41,7 +42,7 @@ import { CLI_VERSION } from './version.js';
|
|
|
41
42
|
* automatically gets json-envelope-conformance coverage the moment it's
|
|
42
43
|
* added here.
|
|
43
44
|
*/
|
|
44
|
-
export const COMMAND_NAMES = ['init', 'doctor'];
|
|
45
|
+
export const COMMAND_NAMES = ['init', 'doctor', 'version'];
|
|
45
46
|
function isCommanderError(err) {
|
|
46
47
|
return typeof err === 'object' && err !== null && 'code' in err && typeof err.code === 'string';
|
|
47
48
|
}
|
|
@@ -72,6 +73,8 @@ async function runCommand(commandName, env, jsonMode, body) {
|
|
|
72
73
|
data: outcome.data,
|
|
73
74
|
exitCode: outcome.exitCode,
|
|
74
75
|
});
|
|
76
|
+
for (const notice of outcome.notices ?? [])
|
|
77
|
+
reporter.warn(notice);
|
|
75
78
|
reporter.emitResult(envelope, outcome.humanSummary);
|
|
76
79
|
return outcome.exitCode;
|
|
77
80
|
}
|
|
@@ -109,7 +112,34 @@ async function runCommand(commandName, env, jsonMode, body) {
|
|
|
109
112
|
* RunEnv, returns the exit code it would have produced — no process-global
|
|
110
113
|
* mutation, no real subprocess required for a unit test.
|
|
111
114
|
*/
|
|
115
|
+
/**
|
|
116
|
+
* commander's own `.version()` writes through configureOutput's writeOut, which
|
|
117
|
+
* this program routes to stderr so parser chatter can never contaminate --json
|
|
118
|
+
* stdout. That is the one place a version query must NOT go, so the flag is
|
|
119
|
+
* recognized ahead of parsing and dispatched to the same command path as the
|
|
120
|
+
* subcommand (design.md D8) — one envelope, on stdout, and the two cannot drift.
|
|
121
|
+
*
|
|
122
|
+
* Only a bare global query is intercepted: a version flag alongside anything
|
|
123
|
+
* other than the global output flags falls through to commander, which reports
|
|
124
|
+
* it as the usage error it is.
|
|
125
|
+
*/
|
|
126
|
+
const VERSION_FLAGS = new Set(['--version', '-V']);
|
|
127
|
+
const GLOBAL_PASSTHROUGH_FLAGS = new Set(['--json', '--no-input']);
|
|
128
|
+
function isGlobalVersionRequest(argv) {
|
|
129
|
+
if (!argv.some((arg) => VERSION_FLAGS.has(arg)))
|
|
130
|
+
return false;
|
|
131
|
+
return argv.every((arg) => VERSION_FLAGS.has(arg) || GLOBAL_PASSTHROUGH_FLAGS.has(arg));
|
|
132
|
+
}
|
|
133
|
+
/** Accumulates a repeatable option's values — commander keeps only the last without it. */
|
|
134
|
+
function collect(value, previous) {
|
|
135
|
+
return [...previous, value];
|
|
136
|
+
}
|
|
112
137
|
export async function run(argv, env) {
|
|
138
|
+
if (isGlobalVersionRequest(argv)) {
|
|
139
|
+
const jsonMode = argv.includes('--json');
|
|
140
|
+
const runEnv = { ...env, noInput: env.noInput || argv.includes('--no-input') || jsonMode };
|
|
141
|
+
return runCommand('version', runEnv, jsonMode, () => versionCommand.execute(runEnv));
|
|
142
|
+
}
|
|
113
143
|
const program = new Command();
|
|
114
144
|
program
|
|
115
145
|
.name('ctxr')
|
|
@@ -118,7 +148,7 @@ export async function run(argv, env) {
|
|
|
118
148
|
writeOut: (str) => env.io.stderr.write(str),
|
|
119
149
|
writeErr: (str) => env.io.stderr.write(str),
|
|
120
150
|
})
|
|
121
|
-
.option('--root <path>', 'store root (overrides
|
|
151
|
+
.option('--root <path>', 'store root (overrides CONTEXTURE_STORE_ROOT)')
|
|
122
152
|
.option('--json', 'emit machine-readable output')
|
|
123
153
|
.option('--no-input', 'never prompt; fail loud instead of blocking');
|
|
124
154
|
let result = ExitCode.Ok;
|
|
@@ -189,6 +219,34 @@ export async function run(argv, env) {
|
|
|
189
219
|
return catalogShowCommand.execute(store, { section: cmdOpts.section });
|
|
190
220
|
});
|
|
191
221
|
});
|
|
222
|
+
const contextCommand = program.command('context').description('the retrieval pass over the store');
|
|
223
|
+
contextCommand
|
|
224
|
+
.command('gather')
|
|
225
|
+
.description('expand entry selectors through the built graph into a gloss-annotated, ordered candidate set — no query, no ranking')
|
|
226
|
+
.option('--seed <path>', 'a note already in hand (repeatable)', collect, [])
|
|
227
|
+
.option('--section <id>', 'every note a catalog section lists (repeatable)', collect, [])
|
|
228
|
+
.option('--under <prefix>', 'every retrievable note under this path prefix (repeatable)', collect, [])
|
|
229
|
+
.option('--entity <name>', 'every note linking to this entity (same enumeration as rollup gather; repeatable)', collect, [])
|
|
230
|
+
.option('--hops <n>', 'how many graph hops to expand from the entry set', (v) => Number.parseInt(v, 10), 1)
|
|
231
|
+
.option('--direction <dir>', 'expand along in, out, or both edge directions', 'both')
|
|
232
|
+
.option('--type <name>', 'expand only along edges of one configured relation')
|
|
233
|
+
.option('--max-notes <n>', 'cap the returned set; truncation is reported, never silent', (v) => Number.parseInt(v, 10))
|
|
234
|
+
.action(async (cmdOpts, cmd) => {
|
|
235
|
+
const { runEnv, jsonMode, root } = deriveRunEnv(env, cmd);
|
|
236
|
+
result = await runCommand('context.gather', runEnv, jsonMode, async () => {
|
|
237
|
+
const store = await openStore(runEnv, { root });
|
|
238
|
+
return contextGatherCommand.execute(store, {
|
|
239
|
+
seed: cmdOpts.seed,
|
|
240
|
+
section: cmdOpts.section,
|
|
241
|
+
under: cmdOpts.under,
|
|
242
|
+
entity: cmdOpts.entity,
|
|
243
|
+
hops: cmdOpts.hops,
|
|
244
|
+
direction: cmdOpts.direction,
|
|
245
|
+
type: cmdOpts.type,
|
|
246
|
+
maxNotes: cmdOpts.maxNotes,
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
192
250
|
const graphCommand = program.command('graph').description('the wikilink graph derived from the store');
|
|
193
251
|
graphCommand
|
|
194
252
|
.command('build')
|
|
@@ -284,15 +342,17 @@ export async function run(argv, env) {
|
|
|
284
342
|
});
|
|
285
343
|
program
|
|
286
344
|
.command('ingest <path>')
|
|
287
|
-
.description('
|
|
345
|
+
.description('retain a capture with its source identity, and cite it from the note it informed')
|
|
346
|
+
.requiredOption('--into <note>', 'the note this material informed — new or existing; ingest never creates it')
|
|
288
347
|
.requiredOption('--source-type <type>', 'the kind of source this material came from')
|
|
289
348
|
.requiredOption('--source-id <id>', 'a stable identifier for this specific source')
|
|
290
|
-
.action(async (
|
|
349
|
+
.action(async (capturePath, cmdOpts, cmd) => {
|
|
291
350
|
const { runEnv, jsonMode, root } = deriveRunEnv(env, cmd);
|
|
292
351
|
result = await runCommand('ingest', runEnv, jsonMode, async () => {
|
|
293
352
|
const store = await openStore(runEnv, { root });
|
|
294
353
|
return ingestCommand.execute(runEnv, store, {
|
|
295
|
-
path:
|
|
354
|
+
path: capturePath,
|
|
355
|
+
into: cmdOpts.into,
|
|
296
356
|
sourceType: cmdOpts.sourceType,
|
|
297
357
|
sourceId: cmdOpts.sourceId,
|
|
298
358
|
});
|
|
@@ -467,6 +527,14 @@ export async function run(argv, env) {
|
|
|
467
527
|
return serveCommand.execute(runEnv, store, { port: cmdOpts.port, host: cmdOpts.host });
|
|
468
528
|
});
|
|
469
529
|
});
|
|
530
|
+
program
|
|
531
|
+
.command('version')
|
|
532
|
+
.description("report the installed ctxr version, where it is installed from, and (with --check) whether a newer release is published")
|
|
533
|
+
.option('--check', 'resolve the latest published release and compare it against the installed one')
|
|
534
|
+
.action(async (cmdOpts, cmd) => {
|
|
535
|
+
const { runEnv, jsonMode } = deriveRunEnv(env, cmd);
|
|
536
|
+
result = await runCommand('version', runEnv, jsonMode, () => versionCommand.execute(runEnv, { check: cmdOpts.check }));
|
|
537
|
+
});
|
|
470
538
|
program
|
|
471
539
|
.command('update')
|
|
472
540
|
.description('bring every contexture-owned file in the store up to the installed version (docs, skills, hooks, adapter outputs)')
|
|
@@ -480,23 +548,12 @@ export async function run(argv, env) {
|
|
|
480
548
|
program
|
|
481
549
|
.command('verify')
|
|
482
550
|
.description('exercise core store operations end to end, from an environment with no harness-specific state')
|
|
483
|
-
.option('--portable',
|
|
551
|
+
.option('--portable', "verify the store's recorded commit in a disposable checkout, in a child process with no harness state reachable")
|
|
484
552
|
.action(async (cmdOpts, cmd) => {
|
|
485
553
|
const { runEnv, jsonMode, root } = deriveRunEnv(env, cmd);
|
|
486
554
|
result = await runCommand('verify', runEnv, jsonMode, async () => {
|
|
487
555
|
const store = await openStore(runEnv, { root });
|
|
488
|
-
return verifyCommand.execute(store, { portable: cmdOpts.portable });
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
program
|
|
492
|
-
.command('migrate')
|
|
493
|
-
.description('apply every pending schema migration, bringing the store up to the current schema_version')
|
|
494
|
-
.option('--dry-run', 'report the exact changes each pending migration would make, without applying them')
|
|
495
|
-
.action(async (cmdOpts, cmd) => {
|
|
496
|
-
const { runEnv, jsonMode, root } = deriveRunEnv(env, cmd);
|
|
497
|
-
result = await runCommand('migrate', runEnv, jsonMode, async () => {
|
|
498
|
-
const store = await openStore(runEnv, { root });
|
|
499
|
-
return migrateCommand.execute(store, { dryRun: cmdOpts.dryRun });
|
|
556
|
+
return verifyCommand.execute(runEnv, store, { portable: cmdOpts.portable });
|
|
500
557
|
});
|
|
501
558
|
});
|
|
502
559
|
const sessionCommand = program.command('session').description('manage session worktrees');
|