ctxr-cli 0.4.1 → 0.6.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/dist/adapter.d.ts +0 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/builtin/index.d.ts.map +1 -1
- package/dist/adapters/builtin/index.js +2 -2
- package/dist/adapters/builtin/index.js.map +1 -1
- package/dist/adapters/harness/claude-code.d.ts.map +1 -1
- package/dist/adapters/harness/claude-code.js +30 -14
- package/dist/adapters/harness/claude-code.js.map +1 -1
- package/dist/adapters/harness/hermes-agent.d.ts +9 -0
- package/dist/adapters/harness/hermes-agent.d.ts.map +1 -0
- package/dist/adapters/harness/hermes-agent.js +13 -0
- package/dist/adapters/harness/hermes-agent.js.map +1 -0
- package/dist/adapters/types.d.ts +39 -18
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js +3 -3
- package/dist/adapters/types.js.map +1 -1
- package/dist/commands/adapters-generate.d.ts +4 -2
- package/dist/commands/adapters-generate.d.ts.map +1 -1
- package/dist/commands/adapters-generate.js +14 -6
- package/dist/commands/adapters-generate.js.map +1 -1
- package/dist/commands/archive.d.ts +4 -2
- package/dist/commands/archive.d.ts.map +1 -1
- package/dist/commands/archive.js +5 -3
- package/dist/commands/archive.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +1 -6
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +132 -18
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/publish-check.d.ts +23 -0
- package/dist/commands/publish-check.d.ts.map +1 -0
- package/dist/commands/publish-check.js +116 -0
- package/dist/commands/publish-check.js.map +1 -0
- package/dist/commands/publish-gather.d.ts +37 -0
- package/dist/commands/publish-gather.d.ts.map +1 -0
- package/dist/commands/publish-gather.js +92 -0
- package/dist/commands/publish-gather.js.map +1 -0
- package/dist/commands/publish-new.d.ts +18 -0
- package/dist/commands/publish-new.d.ts.map +1 -0
- package/dist/commands/publish-new.js +86 -0
- package/dist/commands/publish-new.js.map +1 -0
- package/dist/commands/rollup-write.d.ts.map +1 -1
- package/dist/commands/rollup-write.js +8 -0
- package/dist/commands/rollup-write.js.map +1 -1
- package/dist/commands/serve.d.ts +32 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +170 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/update.js +3 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/verify.d.ts +9 -2
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +46 -23
- package/dist/commands/verify.js.map +1 -1
- package/dist/config/defaults.d.ts +53 -15
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +54 -19
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +49 -12
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +115 -23
- package/dist/config/schema.js.map +1 -1
- package/dist/core/agents-doc.d.ts +63 -12
- package/dist/core/agents-doc.d.ts.map +1 -1
- package/dist/core/agents-doc.js +191 -41
- package/dist/core/agents-doc.js.map +1 -1
- package/dist/core/browse/link-resolver.d.ts +12 -0
- package/dist/core/browse/link-resolver.d.ts.map +1 -0
- package/dist/core/browse/link-resolver.js +12 -0
- package/dist/core/browse/link-resolver.js.map +1 -0
- package/dist/core/browse/render.d.ts +5 -0
- package/dist/core/browse/render.d.ts.map +1 -0
- package/dist/core/browse/render.js +66 -0
- package/dist/core/browse/render.js.map +1 -0
- package/dist/core/browse/routes.d.ts +31 -0
- package/dist/core/browse/routes.d.ts.map +1 -0
- package/dist/core/browse/routes.js +56 -0
- package/dist/core/browse/routes.js.map +1 -0
- package/dist/core/browse/templates.d.ts +4 -0
- package/dist/core/browse/templates.d.ts.map +1 -0
- package/dist/core/browse/templates.js +26 -0
- package/dist/core/browse/templates.js.map +1 -0
- package/dist/core/checks/harness-portability-checks.d.ts +12 -0
- package/dist/core/checks/harness-portability-checks.d.ts.map +1 -0
- package/dist/core/checks/harness-portability-checks.js +39 -0
- package/dist/core/checks/harness-portability-checks.js.map +1 -0
- package/dist/core/checks/integrity-checks.d.ts +43 -3
- package/dist/core/checks/integrity-checks.d.ts.map +1 -1
- package/dist/core/checks/integrity-checks.js +191 -13
- 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 +21 -1
- package/dist/core/checks/organize-checks.d.ts.map +1 -1
- package/dist/core/checks/organize-checks.js +64 -4
- package/dist/core/checks/organize-checks.js.map +1 -1
- package/dist/core/convention-doc.d.ts +32 -0
- package/dist/core/convention-doc.d.ts.map +1 -0
- package/dist/core/convention-doc.js +137 -0
- package/dist/core/convention-doc.js.map +1 -0
- package/dist/core/conventions.d.ts +25 -5
- package/dist/core/conventions.d.ts.map +1 -1
- package/dist/core/conventions.js +65 -3
- package/dist/core/conventions.js.map +1 -1
- package/dist/core/disclosure/model.d.ts +11 -0
- package/dist/core/disclosure/model.d.ts.map +1 -1
- package/dist/core/disclosure/model.js +24 -0
- package/dist/core/disclosure/model.js.map +1 -1
- package/dist/core/errors.d.ts +27 -41
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +76 -119
- package/dist/core/errors.js.map +1 -1
- package/dist/core/fs/fenced-region.d.ts +38 -0
- package/dist/core/fs/fenced-region.d.ts.map +1 -1
- package/dist/core/fs/fenced-region.js +88 -2
- package/dist/core/fs/fenced-region.js.map +1 -1
- package/dist/core/git/repo.d.ts +0 -6
- package/dist/core/git/repo.d.ts.map +1 -1
- package/dist/core/git/repo.js +0 -13
- package/dist/core/git/repo.js.map +1 -1
- package/dist/core/git/worktree.d.ts +4 -7
- package/dist/core/git/worktree.d.ts.map +1 -1
- package/dist/core/git/worktree.js +4 -10
- package/dist/core/git/worktree.js.map +1 -1
- package/dist/core/graph/model.d.ts +14 -0
- package/dist/core/graph/model.d.ts.map +1 -1
- package/dist/core/graph/model.js +30 -14
- package/dist/core/graph/model.js.map +1 -1
- package/dist/core/harness/bridge.d.ts +30 -0
- package/dist/core/harness/bridge.d.ts.map +1 -0
- package/dist/core/harness/bridge.js +178 -0
- package/dist/core/harness/bridge.js.map +1 -0
- package/dist/core/json-config-merge.d.ts.map +1 -1
- package/dist/core/json-config-merge.js +30 -7
- package/dist/core/json-config-merge.js.map +1 -1
- package/dist/core/migrations/archive-destination-from-taxonomy.d.ts +35 -0
- package/dist/core/migrations/archive-destination-from-taxonomy.d.ts.map +1 -0
- package/dist/core/migrations/archive-destination-from-taxonomy.js +109 -0
- package/dist/core/migrations/archive-destination-from-taxonomy.js.map +1 -0
- package/dist/core/migrations/drop-forge-and-workspaces-external.d.ts +19 -0
- package/dist/core/migrations/drop-forge-and-workspaces-external.d.ts.map +1 -0
- package/dist/core/migrations/drop-forge-and-workspaces-external.js +49 -0
- package/dist/core/migrations/drop-forge-and-workspaces-external.js.map +1 -0
- package/dist/core/migrations/registry.d.ts.map +1 -1
- package/dist/core/migrations/registry.js +10 -1
- package/dist/core/migrations/registry.js.map +1 -1
- package/dist/core/migrations/rename-conventions-path.d.ts +26 -0
- package/dist/core/migrations/rename-conventions-path.d.ts.map +1 -0
- package/dist/core/migrations/rename-conventions-path.js +86 -0
- package/dist/core/migrations/rename-conventions-path.js.map +1 -0
- package/dist/core/notes/list.d.ts.map +1 -1
- package/dist/core/notes/list.js +7 -3
- package/dist/core/notes/list.js.map +1 -1
- package/dist/core/publish/script-check.d.ts +12 -0
- package/dist/core/publish/script-check.d.ts.map +1 -0
- package/dist/core/publish/script-check.js +39 -0
- package/dist/core/publish/script-check.js.map +1 -0
- package/dist/core/reconcile.d.ts +3 -0
- package/dist/core/reconcile.d.ts.map +1 -1
- package/dist/core/reconcile.js +43 -6
- package/dist/core/reconcile.js.map +1 -1
- package/dist/core/rollup.d.ts +2 -2
- package/dist/core/rollup.d.ts.map +1 -1
- package/dist/core/rollup.js +24 -3
- package/dist/core/rollup.js.map +1 -1
- package/dist/core/session.d.ts +9 -9
- package/dist/core/session.js +9 -9
- package/dist/core/skills.d.ts +36 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +154 -29
- package/dist/core/skills.js.map +1 -1
- package/dist/core/write-lifecycle/path-gate.d.ts.map +1 -1
- package/dist/core/write-lifecycle/path-gate.js +5 -3
- package/dist/core/write-lifecycle/path-gate.js.map +1 -1
- package/dist/prompt/inquirer-prompter.d.ts.map +1 -1
- package/dist/prompt/inquirer-prompter.js +11 -1
- package/dist/prompt/inquirer-prompter.js.map +1 -1
- package/dist/prompt/prompter.d.ts +16 -0
- package/dist/prompt/prompter.d.ts.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +61 -55
- package/dist/run.js.map +1 -1
- package/dist/taxonomy/profiles.d.ts +11 -0
- package/dist/taxonomy/profiles.d.ts.map +1 -1
- package/dist/taxonomy/profiles.js +1 -0
- package/dist/taxonomy/profiles.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -1
- package/templates/agents/canonical.md +2 -8
- package/templates/agents/{store-conventions.md → conventions.md} +2 -4
- package/templates/agents/mission.md +5 -0
- package/templates/conventions/baseline-conventions.md +60 -0
- package/templates/conventions/house-conventions-seed.md +34 -0
- package/templates/hooks/pre-push.sh +1 -1
- package/templates/serve/shell.html +15 -0
- package/templates/serve/style.css +88 -0
- package/templates/skills/ctxr-land.md +32 -18
- package/templates/skills/ctxr-organize-audit.md +1 -1
- package/templates/skills/ctxr-publish.md +79 -0
- package/templates/skills/ctxr-session-capture.md +44 -1
- package/templates/skills/ctxr-session-lifecycle.md +20 -1
- package/templates/skills/ctxr-submit.md +15 -11
- package/templates/vendor/frontend-design/LICENSE.txt +177 -0
- package/templates/vendor/frontend-design/SKILL.md +55 -0
- package/templates/vendor/frontend-design/provenance.json +7 -0
- package/dist/adapters/forge/github.d.ts +0 -12
- package/dist/adapters/forge/github.d.ts.map +0 -1
- package/dist/adapters/forge/github.js +0 -76
- package/dist/adapters/forge/github.js.map +0 -1
- package/dist/adapters/forge/types.d.ts +0 -46
- package/dist/adapters/forge/types.d.ts.map +0 -1
- package/dist/adapters/forge/types.js +0 -2
- package/dist/adapters/forge/types.js.map +0 -1
- package/dist/commands/session-abandon.d.ts +0 -13
- package/dist/commands/session-abandon.d.ts.map +0 -1
- package/dist/commands/session-abandon.js +0 -22
- package/dist/commands/session-abandon.js.map +0 -1
- package/dist/commands/session-land.d.ts +0 -45
- package/dist/commands/session-land.d.ts.map +0 -1
- package/dist/commands/session-land.js +0 -171
- package/dist/commands/session-land.js.map +0 -1
- package/dist/commands/session-reap.d.ts +0 -22
- package/dist/commands/session-reap.d.ts.map +0 -1
- package/dist/commands/session-reap.js +0 -52
- package/dist/commands/session-reap.js.map +0 -1
- package/dist/commands/session-submit.d.ts +0 -29
- package/dist/commands/session-submit.d.ts.map +0 -1
- package/dist/commands/session-submit.js +0 -72
- package/dist/commands/session-submit.js.map +0 -1
- package/templates/agents/store-conventions-empty.md +0 -7
|
@@ -45,28 +45,79 @@ export declare function buildAgentsPlacementSection(root: string, config: StoreC
|
|
|
45
45
|
changed: boolean;
|
|
46
46
|
}>;
|
|
47
47
|
/**
|
|
48
|
-
* harness-portability spec (
|
|
49
|
-
* required pieces — root-resolution rule, frontmatter schema
|
|
50
|
-
* write-path rule, and
|
|
51
|
-
* this file, with no harness-specific context, has
|
|
52
|
-
* (the spec's own "Reading only AGENTS.md is
|
|
48
|
+
* harness-portability spec (inline-conventions-and-mission): the canonical
|
|
49
|
+
* template's required pieces — root-resolution rule, frontmatter schema
|
|
50
|
+
* pointer, write-path rule, and the harness/store identity boundary — so an
|
|
51
|
+
* agent that has read only this file, with no harness-specific context, has
|
|
52
|
+
* everything it needs (the spec's own "Reading only AGENTS.md is
|
|
53
|
+
* sufficient" scenario). The skill index this section used to carry is gone
|
|
54
|
+
* (see the REMOVED "The skill index reflects the files on disk" requirement)
|
|
55
|
+
* — on a harness with native skill auto-discovery it duplicated content
|
|
56
|
+
* already in context; a harness without one still reaches every skill by
|
|
57
|
+
* path at the configured skills path.
|
|
53
58
|
*/
|
|
54
59
|
export declare const AGENTS_MD_CANONICAL_FENCE: import("./markers.js").Fence;
|
|
55
|
-
export declare function renderCanonicalSection(config: StoreConfig
|
|
60
|
+
export declare function renderCanonicalSection(config: StoreConfig): string[];
|
|
56
61
|
export declare function buildAgentsCanonicalSection(root: string, config: StoreConfig): Promise<{
|
|
57
62
|
changed: boolean;
|
|
58
63
|
}>;
|
|
59
64
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
65
|
+
* inline-conventions-and-mission: the store's current mission, inlined as
|
|
66
|
+
* its own fenced section — replacing the pointer-only rendering this used to
|
|
67
|
+
* get. `missionRaw` is the mission note's raw file content, read by the
|
|
68
|
+
* caller (`buildAgentsMissionSection`) so this stays a pure, synchronous
|
|
69
|
+
* renderer like every other section in this file; `null` means unconfigured
|
|
70
|
+
* or the note doesn't exist, either of which renders nothing at all.
|
|
71
|
+
*/
|
|
72
|
+
export declare const AGENTS_MD_MISSION_FENCE: import("./markers.js").Fence;
|
|
73
|
+
export declare function renderMissionSection(config: StoreConfig, missionRaw: string | null): string[];
|
|
74
|
+
export declare function buildAgentsMissionSection(root: string, config: StoreConfig): Promise<{
|
|
75
|
+
changed: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* harness-portability spec (inline-conventions-and-mission, folded into one
|
|
79
|
+
* template by compose-store-guidance-documents): operator conventions
|
|
80
|
+
* inlined in full. What's on disk at the configured conventions path is
|
|
81
|
+
* inlined body-and-all — heading-demoted under a heading naming its title,
|
|
82
|
+
* with a provenance line naming its source path — never referenced by a
|
|
83
|
+
* link alone; contexture ships no seeds here — conventions are
|
|
84
|
+
* definitionally operator-authored, so an empty store gets an explanation of
|
|
85
|
+
* the mechanism instead. One template (`conventions.md`) carries both: the
|
|
86
|
+
* empty-vs-populated difference is entirely in the lines `renderConventionsSection`
|
|
87
|
+
* computes for its one `__CONVENTION_BODY__` slot, so the surrounding frame
|
|
88
|
+
* (heading, harness-specific-note paragraph) exists in exactly one place and
|
|
89
|
+
* cannot drift between two copies the way it could when it shipped as two
|
|
90
|
+
* separate template files.
|
|
66
91
|
*/
|
|
67
92
|
export declare const AGENTS_MD_CONVENTIONS_FENCE: import("./markers.js").Fence;
|
|
93
|
+
/** Exported so doctor/verify can check a specific convention file's inlined block for drift without re-deriving the format. */
|
|
94
|
+
export declare function renderConventionBlock(doc: ScannedDoc): string[];
|
|
68
95
|
export declare function renderConventionsSection(config: StoreConfig, conventions: readonly ScannedDoc[]): string[];
|
|
69
96
|
export declare function buildAgentsConventionsSection(root: string, config: StoreConfig): Promise<{
|
|
70
97
|
changed: boolean;
|
|
71
98
|
}>;
|
|
99
|
+
/**
|
|
100
|
+
* harness-portability spec: "Generated sections render in a fixed order" —
|
|
101
|
+
* hard rules and current state first, operating mechanics next, the long
|
|
102
|
+
* operator reference last. `reconcileStore` passes this straight to
|
|
103
|
+
* `reorderFencedRegionsInFile`; a mission-less store simply never has the
|
|
104
|
+
* mission fence present, which the reorder primitive already treats as
|
|
105
|
+
* "skip it," not an error.
|
|
106
|
+
*/
|
|
107
|
+
export declare const AGENTS_MD_SECTION_ORDER: import("./markers.js").Fence[];
|
|
108
|
+
export interface AgentsMdDrift {
|
|
109
|
+
/** Store-relative paths of convention files whose inlined block no longer matches the source. */
|
|
110
|
+
driftedConventions: string[];
|
|
111
|
+
/** The configured mission path, when its inlined section no longer matches the source; null otherwise. */
|
|
112
|
+
driftedMission: string | null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* harness-portability spec: "The entry document's inlined content matches
|
|
116
|
+
* its sources" — shared by `ctxr doctor` (reports every drifted file) and
|
|
117
|
+
* `ctxr verify --portable` (stops at the first one), per design.md's
|
|
118
|
+
* "Drift detection reuses render, not a hash": re-runs the same renderers
|
|
119
|
+
* `buildAgents*Section` uses and diffs against what is currently inside each
|
|
120
|
+
* fence, rather than storing a separate content hash anywhere.
|
|
121
|
+
*/
|
|
122
|
+
export declare function checkAgentsMdDrift(root: string, config: StoreConfig): Promise<AgentsMdDrift>;
|
|
72
123
|
//# sourceMappingURL=agents-doc.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-doc.d.ts","sourceRoot":"","sources":["../../src/core/agents-doc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agents-doc.d.ts","sourceRoot":"","sources":["../../src/core/agents-doc.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,OAAO,EAAsD,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAgBvG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,8BAA4C,CAAC;AAgCrF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAOrE;AAED,mHAAmH;AACnH,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAEnH;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,8BAAyC,CAAC;AAE9E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAElE;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAEhH;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,8BAAgC,CAAC;AAEvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAapE;AAED,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAElH;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,yBAAyB,8BAAgC,CAAC;AAuBvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAUpE;AAED,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAElH;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AAEnE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAS7F;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAoBhH;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,2BAA2B,8BAAkC,CAAC;AAE3E,+HAA+H;AAC/H,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,EAAE,CAE/D;AAeD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,EAAE,CAE1G;AAED,wBAAsB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAGpH;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,gCAOnC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,iGAAiG;IACjG,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,0GAA0G;IAC1G,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAoClG"}
|
package/dist/core/agents-doc.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { GRAPH_DOCUMENT_RELATIVE_PATH } from './graph/persist.js';
|
|
3
4
|
import { CONFIG_FILE_NAME } from './root.js';
|
|
4
5
|
import { excludedPrefixesFor } from './notes/list.js';
|
|
5
|
-
import { scanConventions } from './conventions.js';
|
|
6
|
-
import {
|
|
7
|
-
import { upsertFencedRegionInFile } from './fs/fenced-region.js';
|
|
6
|
+
import { extractDocMetadata, inlineDocBody, scanConventions } from './conventions.js';
|
|
7
|
+
import { readFencedRegionFromFile, removeFencedRegionFromFile, upsertFencedRegionInFile } from './fs/fenced-region.js';
|
|
8
8
|
import { htmlCommentFence } from './markers.js';
|
|
9
9
|
import { packagedTemplate, substituteBlock } from './templates.js';
|
|
10
10
|
/**
|
|
@@ -17,10 +17,6 @@ import { packagedTemplate, substituteBlock } from './templates.js';
|
|
|
17
17
|
function agentsTemplate(name) {
|
|
18
18
|
return packagedTemplate('agents', name);
|
|
19
19
|
}
|
|
20
|
-
/** The one index-entry format both the skill and convention indexes use. */
|
|
21
|
-
function docIndexEntry(doc) {
|
|
22
|
-
return `- [${doc.title}](${doc.path})${doc.description ? ` — ${doc.description}` : ''}`;
|
|
23
|
-
}
|
|
24
20
|
export function agentsMdPath(root) {
|
|
25
21
|
return path.join(root, 'AGENTS.md');
|
|
26
22
|
}
|
|
@@ -34,9 +30,38 @@ export function agentsMdPath(root) {
|
|
|
34
30
|
* index) as sibling regions in the same file, never touching this one.
|
|
35
31
|
*/
|
|
36
32
|
export const AGENTS_MD_LEG_ROUTING_FENCE = htmlCommentFence('retrieval-leg-routing');
|
|
33
|
+
function trimTrailingSlash(prefix) {
|
|
34
|
+
return prefix.replace(/\/+$/, '');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* inline-conventions-and-mission: `excludedPrefixesFor` deliberately includes
|
|
38
|
+
* both a parent path (e.g. `.contexture/`) and paths nested under it (e.g.
|
|
39
|
+
* `.contexture/cache/`) — each has its own reason to be there, and the note
|
|
40
|
+
* walker (`notes/list.ts`) needs the full, unfiltered set to skip directories
|
|
41
|
+
* early rather than descend and filter every file. Rendering that list
|
|
42
|
+
* verbatim produces a dozen-plus redundant bullets, so this collapses any
|
|
43
|
+
* prefix already covered by an ancestor prefix for display only — the
|
|
44
|
+
* exclusion logic itself is untouched.
|
|
45
|
+
*/
|
|
46
|
+
function collapseNestedPrefixes(prefixes) {
|
|
47
|
+
// Original (possibly trailing-slash) form preserved per trimmed key, since
|
|
48
|
+
// this list mixes directory prefixes and bare file exclusions (AGENTS.md,
|
|
49
|
+
// log.md) — the collapse test itself compares on the trimmed form only.
|
|
50
|
+
const originalByTrimmed = new Map();
|
|
51
|
+
for (const prefix of prefixes) {
|
|
52
|
+
const trimmed = trimTrailingSlash(prefix);
|
|
53
|
+
if (!originalByTrimmed.has(trimmed))
|
|
54
|
+
originalByTrimmed.set(trimmed, prefix);
|
|
55
|
+
}
|
|
56
|
+
const trimmed = [...originalByTrimmed.keys()];
|
|
57
|
+
return trimmed
|
|
58
|
+
.filter((path) => !trimmed.some((other) => other !== path && path.startsWith(`${other}/`)))
|
|
59
|
+
.sort()
|
|
60
|
+
.map((path) => originalByTrimmed.get(path));
|
|
61
|
+
}
|
|
37
62
|
export function renderLegRoutingSection(config) {
|
|
38
|
-
const exclusions =
|
|
39
|
-
return substituteBlock(agentsTemplate('retrieval-leg-routing').replaceAll('__GRAPH_DOCUMENT_PATH__', GRAPH_DOCUMENT_RELATIVE_PATH), '__EXCLUSION_PATHS__', exclusions.map((prefix) =>
|
|
63
|
+
const exclusions = collapseNestedPrefixes(excludedPrefixesFor(config));
|
|
64
|
+
return substituteBlock(agentsTemplate('retrieval-leg-routing').replaceAll('__GRAPH_DOCUMENT_PATH__', GRAPH_DOCUMENT_RELATIVE_PATH), '__EXCLUSION_PATHS__', [exclusions.map((prefix) => `\`${prefix}\``).join(', ')]).split('\n');
|
|
40
65
|
}
|
|
41
66
|
/** Idempotently reconciles AGENTS.md's leg-routing section from current config — called at init and on re-init. */
|
|
42
67
|
export async function buildAgentsLegRoutingSection(root, config) {
|
|
@@ -82,22 +107,28 @@ export async function buildAgentsPlacementSection(root, config) {
|
|
|
82
107
|
return upsertFencedRegionInFile(agentsMdPath(root), AGENTS_MD_PLACEMENT_FENCE, renderPlacementSection(config));
|
|
83
108
|
}
|
|
84
109
|
/**
|
|
85
|
-
* harness-portability spec (
|
|
86
|
-
* required pieces — root-resolution rule, frontmatter schema
|
|
87
|
-
* write-path rule, and
|
|
88
|
-
* this file, with no harness-specific context, has
|
|
89
|
-
* (the spec's own "Reading only AGENTS.md is
|
|
110
|
+
* harness-portability spec (inline-conventions-and-mission): the canonical
|
|
111
|
+
* template's required pieces — root-resolution rule, frontmatter schema
|
|
112
|
+
* pointer, write-path rule, and the harness/store identity boundary — so an
|
|
113
|
+
* agent that has read only this file, with no harness-specific context, has
|
|
114
|
+
* everything it needs (the spec's own "Reading only AGENTS.md is
|
|
115
|
+
* sufficient" scenario). The skill index this section used to carry is gone
|
|
116
|
+
* (see the REMOVED "The skill index reflects the files on disk" requirement)
|
|
117
|
+
* — on a harness with native skill auto-discovery it duplicated content
|
|
118
|
+
* already in context; a harness without one still reaches every skill by
|
|
119
|
+
* path at the configured skills path.
|
|
90
120
|
*/
|
|
91
121
|
export const AGENTS_MD_CANONICAL_FENCE = htmlCommentFence('canonical');
|
|
92
122
|
/**
|
|
93
|
-
* context-organize spec
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* `__MISSION_POINTER__` template line
|
|
100
|
-
* `substituteBlock`'s empty-list case), not a
|
|
123
|
+
* context-organize spec, kept through inline-conventions-and-mission's
|
|
124
|
+
* design decision "the identity/mission pointer coexists with the inlined
|
|
125
|
+
* Mission section": when `organize.mission_path` is configured, the
|
|
126
|
+
* canonical section still names it as a document to load at session start,
|
|
127
|
+
* immediately followed (as its own fenced section — see
|
|
128
|
+
* `renderMissionSection` below) by that document's full inlined body.
|
|
129
|
+
* Nothing is rendered when unset: the `__MISSION_POINTER__` template line
|
|
130
|
+
* disappears entirely (via `substituteBlock`'s empty-list case), not a
|
|
131
|
+
* placeholder.
|
|
101
132
|
*/
|
|
102
133
|
function renderMissionPointer(config) {
|
|
103
134
|
const { mission_path: missionPath } = config.organize;
|
|
@@ -106,40 +137,159 @@ function renderMissionPointer(config) {
|
|
|
106
137
|
return [
|
|
107
138
|
'',
|
|
108
139
|
`Load \`${missionPath}\` at the start of every session — this store's standing current-state document, ` +
|
|
109
|
-
'kept current by the mission skill
|
|
140
|
+
'kept current by the mission skill and written through `ctxr rollup write`; its full content follows in the "Mission" section below.',
|
|
110
141
|
];
|
|
111
142
|
}
|
|
112
|
-
export function renderCanonicalSection(config
|
|
113
|
-
|
|
143
|
+
export function renderCanonicalSection(config) {
|
|
144
|
+
return substituteBlock(agentsTemplate('canonical')
|
|
114
145
|
.replaceAll('__CONFIG_FILE_NAME__', CONFIG_FILE_NAME)
|
|
115
146
|
.replaceAll('__VISIBILITY_FIELD__', config.fields.visibility)
|
|
116
147
|
.replaceAll('__DEFAULT_CONTEXT__', config.visibility.default_context)
|
|
117
|
-
.replaceAll('__SKILLS_PATH__', config.harness.skills_path), '__MISSION_POINTER__', renderMissionPointer(config));
|
|
118
|
-
return substituteBlock(text, '__SKILL_INDEX__', skills.map(docIndexEntry)).split('\n');
|
|
148
|
+
.replaceAll('__SKILLS_PATH__', config.harness.skills_path), '__MISSION_POINTER__', renderMissionPointer(config)).split('\n');
|
|
119
149
|
}
|
|
120
150
|
export async function buildAgentsCanonicalSection(root, config) {
|
|
121
|
-
|
|
122
|
-
return upsertFencedRegionInFile(agentsMdPath(root), AGENTS_MD_CANONICAL_FENCE, renderCanonicalSection(config, skills));
|
|
151
|
+
return upsertFencedRegionInFile(agentsMdPath(root), AGENTS_MD_CANONICAL_FENCE, renderCanonicalSection(config));
|
|
123
152
|
}
|
|
124
153
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
154
|
+
* inline-conventions-and-mission: the store's current mission, inlined as
|
|
155
|
+
* its own fenced section — replacing the pointer-only rendering this used to
|
|
156
|
+
* get. `missionRaw` is the mission note's raw file content, read by the
|
|
157
|
+
* caller (`buildAgentsMissionSection`) so this stays a pure, synchronous
|
|
158
|
+
* renderer like every other section in this file; `null` means unconfigured
|
|
159
|
+
* or the note doesn't exist, either of which renders nothing at all.
|
|
131
160
|
*/
|
|
132
|
-
export const
|
|
133
|
-
export function
|
|
161
|
+
export const AGENTS_MD_MISSION_FENCE = htmlCommentFence('mission');
|
|
162
|
+
export function renderMissionSection(config, missionRaw) {
|
|
163
|
+
const { mission_path: missionPath } = config.organize;
|
|
164
|
+
if (!missionPath || missionRaw === null)
|
|
165
|
+
return [];
|
|
166
|
+
const doc = extractDocMetadata(missionRaw, missionPath);
|
|
167
|
+
return substituteBlock(agentsTemplate('mission').replaceAll('__MISSION_PATH__', missionPath), '__MISSION_BODY__', inlineDocBody(doc, 1)).split('\n');
|
|
168
|
+
}
|
|
169
|
+
export async function buildAgentsMissionSection(root, config) {
|
|
170
|
+
const { mission_path: missionPath } = config.organize;
|
|
171
|
+
let missionRaw = null;
|
|
172
|
+
if (missionPath) {
|
|
173
|
+
try {
|
|
174
|
+
missionRaw = await readFile(path.join(root, missionPath), 'utf8');
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
if (err.code !== 'ENOENT')
|
|
178
|
+
throw err;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const body = renderMissionSection(config, missionRaw);
|
|
182
|
+
// `upsertFencedRegionInFile` appends a fence pair unconditionally when it's
|
|
183
|
+
// absent, even with an empty body — wrong here, where "unconfigured" must
|
|
184
|
+
// mean the section is absent entirely, never an empty fence pair. Removal
|
|
185
|
+
// is idempotent (a no-op when the fence isn't there), so this also cleans
|
|
186
|
+
// up correctly if a store had a mission configured and then unset it.
|
|
187
|
+
if (body.length === 0) {
|
|
188
|
+
return removeFencedRegionFromFile(agentsMdPath(root), AGENTS_MD_MISSION_FENCE);
|
|
189
|
+
}
|
|
190
|
+
return upsertFencedRegionInFile(agentsMdPath(root), AGENTS_MD_MISSION_FENCE, body);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* harness-portability spec (inline-conventions-and-mission, folded into one
|
|
194
|
+
* template by compose-store-guidance-documents): operator conventions
|
|
195
|
+
* inlined in full. What's on disk at the configured conventions path is
|
|
196
|
+
* inlined body-and-all — heading-demoted under a heading naming its title,
|
|
197
|
+
* with a provenance line naming its source path — never referenced by a
|
|
198
|
+
* link alone; contexture ships no seeds here — conventions are
|
|
199
|
+
* definitionally operator-authored, so an empty store gets an explanation of
|
|
200
|
+
* the mechanism instead. One template (`conventions.md`) carries both: the
|
|
201
|
+
* empty-vs-populated difference is entirely in the lines `renderConventionsSection`
|
|
202
|
+
* computes for its one `__CONVENTION_BODY__` slot, so the surrounding frame
|
|
203
|
+
* (heading, harness-specific-note paragraph) exists in exactly one place and
|
|
204
|
+
* cannot drift between two copies the way it could when it shipped as two
|
|
205
|
+
* separate template files.
|
|
206
|
+
*/
|
|
207
|
+
export const AGENTS_MD_CONVENTIONS_FENCE = htmlCommentFence('conventions');
|
|
208
|
+
/** Exported so doctor/verify can check a specific convention file's inlined block for drift without re-deriving the format. */
|
|
209
|
+
export function renderConventionBlock(doc) {
|
|
210
|
+
return [`### ${doc.title}`, '', ...inlineDocBody(doc, 2), '', `_Source: ${doc.path}_`];
|
|
211
|
+
}
|
|
212
|
+
function conventionsBody(config, conventions) {
|
|
134
213
|
if (conventions.length === 0) {
|
|
135
|
-
return
|
|
136
|
-
.
|
|
137
|
-
.
|
|
214
|
+
return [
|
|
215
|
+
'This store declares no convention documents yet. Operator-authored conventions (content style, field',
|
|
216
|
+
`semantics, house rules) belong as markdown files under \`${config.harness.guidance_path}\` — each is`,
|
|
217
|
+
'inlined here in full on regeneration.',
|
|
218
|
+
];
|
|
138
219
|
}
|
|
139
|
-
|
|
220
|
+
const blocks = conventions.map(renderConventionBlock);
|
|
221
|
+
const bodies = blocks.flatMap((block, i) => (i === blocks.length - 1 ? block : [...block, '']));
|
|
222
|
+
return ['Operator-authored conventions for this store, inlined in full:', '', ...bodies];
|
|
223
|
+
}
|
|
224
|
+
export function renderConventionsSection(config, conventions) {
|
|
225
|
+
return substituteBlock(agentsTemplate('conventions'), '__CONVENTION_BODY__', conventionsBody(config, conventions)).split('\n');
|
|
140
226
|
}
|
|
141
227
|
export async function buildAgentsConventionsSection(root, config) {
|
|
142
228
|
const conventions = await scanConventions(root, config);
|
|
143
229
|
return upsertFencedRegionInFile(agentsMdPath(root), AGENTS_MD_CONVENTIONS_FENCE, renderConventionsSection(config, conventions));
|
|
144
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* harness-portability spec: "Generated sections render in a fixed order" —
|
|
233
|
+
* hard rules and current state first, operating mechanics next, the long
|
|
234
|
+
* operator reference last. `reconcileStore` passes this straight to
|
|
235
|
+
* `reorderFencedRegionsInFile`; a mission-less store simply never has the
|
|
236
|
+
* mission fence present, which the reorder primitive already treats as
|
|
237
|
+
* "skip it," not an error.
|
|
238
|
+
*/
|
|
239
|
+
export const AGENTS_MD_SECTION_ORDER = [
|
|
240
|
+
AGENTS_MD_CANONICAL_FENCE,
|
|
241
|
+
AGENTS_MD_MISSION_FENCE,
|
|
242
|
+
AGENTS_MD_LEG_ROUTING_FENCE,
|
|
243
|
+
AGENTS_MD_CAPTURE_FENCE,
|
|
244
|
+
AGENTS_MD_PLACEMENT_FENCE,
|
|
245
|
+
AGENTS_MD_CONVENTIONS_FENCE,
|
|
246
|
+
];
|
|
247
|
+
/**
|
|
248
|
+
* harness-portability spec: "The entry document's inlined content matches
|
|
249
|
+
* its sources" — shared by `ctxr doctor` (reports every drifted file) and
|
|
250
|
+
* `ctxr verify --portable` (stops at the first one), per design.md's
|
|
251
|
+
* "Drift detection reuses render, not a hash": re-runs the same renderers
|
|
252
|
+
* `buildAgents*Section` uses and diffs against what is currently inside each
|
|
253
|
+
* fence, rather than storing a separate content hash anywhere.
|
|
254
|
+
*/
|
|
255
|
+
export async function checkAgentsMdDrift(root, config) {
|
|
256
|
+
const filePath = agentsMdPath(root);
|
|
257
|
+
const conventions = await scanConventions(root, config);
|
|
258
|
+
const conventionsRegion = (await readFencedRegionFromFile(filePath, AGENTS_MD_CONVENTIONS_FENCE)).join('\n');
|
|
259
|
+
const freshConventionsSection = renderConventionsSection(config, conventions).join('\n');
|
|
260
|
+
const driftedConventions = [];
|
|
261
|
+
if (freshConventionsSection !== conventionsRegion) {
|
|
262
|
+
if (conventions.length === 0) {
|
|
263
|
+
driftedConventions.push(config.harness.guidance_path);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
for (const doc of conventions) {
|
|
267
|
+
if (!conventionsRegion.includes(renderConventionBlock(doc).join('\n')))
|
|
268
|
+
driftedConventions.push(doc.path);
|
|
269
|
+
}
|
|
270
|
+
// Every individual block present, yet the whole section still differs
|
|
271
|
+
// (a reordering, an added/removed file, a template change): still real
|
|
272
|
+
// drift, just not attributable to one file — report the whole set.
|
|
273
|
+
if (driftedConventions.length === 0)
|
|
274
|
+
driftedConventions.push(...conventions.map((doc) => doc.path));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
let driftedMission = null;
|
|
278
|
+
const missionPath = config.organize.mission_path;
|
|
279
|
+
if (missionPath) {
|
|
280
|
+
let missionRaw = null;
|
|
281
|
+
try {
|
|
282
|
+
missionRaw = await readFile(path.join(root, missionPath), 'utf8');
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
if (err.code !== 'ENOENT')
|
|
286
|
+
throw err;
|
|
287
|
+
}
|
|
288
|
+
const missionRegion = (await readFencedRegionFromFile(filePath, AGENTS_MD_MISSION_FENCE)).join('\n');
|
|
289
|
+
const freshMissionSection = renderMissionSection(config, missionRaw).join('\n');
|
|
290
|
+
if (freshMissionSection !== missionRegion)
|
|
291
|
+
driftedMission = missionPath;
|
|
292
|
+
}
|
|
293
|
+
return { driftedConventions, driftedMission };
|
|
294
|
+
}
|
|
145
295
|
//# sourceMappingURL=agents-doc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-doc.js","sourceRoot":"","sources":["../../src/core/agents-doc.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAmB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"agents-doc.js","sourceRoot":"","sources":["../../src/core/agents-doc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type StemResolution } from '../graph/model.js';
|
|
2
|
+
import type { Note } from '../notes/list.js';
|
|
3
|
+
/** A wikilink target -> a resolved note path, or a reason it didn't resolve to exactly one note. */
|
|
4
|
+
export type LinkResolver = (target: string) => StemResolution;
|
|
5
|
+
/**
|
|
6
|
+
* local-browsing-surface design.md D3: backed by the exact same stem index
|
|
7
|
+
* `ctxr graph build` resolves wikilinks against, so a note that renders
|
|
8
|
+
* cleanly in the browser view is, by construction, a note the graph build
|
|
9
|
+
* also resolves cleanly — never a second, potentially divergent resolver.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildLinkResolver(notes: readonly Note[]): LinkResolver;
|
|
12
|
+
//# sourceMappingURL=link-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-resolver.d.ts","sourceRoot":"","sources":["../../../src/core/browse/link-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,oGAAoG;AACpG,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,cAAc,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,YAAY,CAGtE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { buildStemIndex, resolveStem } from '../graph/model.js';
|
|
2
|
+
/**
|
|
3
|
+
* local-browsing-surface design.md D3: backed by the exact same stem index
|
|
4
|
+
* `ctxr graph build` resolves wikilinks against, so a note that renders
|
|
5
|
+
* cleanly in the browser view is, by construction, a note the graph build
|
|
6
|
+
* also resolves cleanly — never a second, potentially divergent resolver.
|
|
7
|
+
*/
|
|
8
|
+
export function buildLinkResolver(notes) {
|
|
9
|
+
const stemIndex = buildStemIndex(notes);
|
|
10
|
+
return (target) => resolveStem(stemIndex, target);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=link-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-resolver.js","sourceRoot":"","sources":["../../../src/core/browse/link-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAuB,MAAM,mBAAmB,CAAC;AAMrF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,CAAC,MAAc,EAAE,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LinkResolver } from './link-resolver.js';
|
|
2
|
+
export declare function escapeHtml(text: string): string;
|
|
3
|
+
/** Renders a note's markdown body to HTML, with wikilinks resolved via `resolveLink` (design.md D3). */
|
|
4
|
+
export declare function renderNoteBody(body: string, resolveLink: LinkResolver): string;
|
|
5
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/core/browse/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA+CvD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM/C;AAuBD,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,GAAG,MAAM,CAE9E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import MarkdownIt from 'markdown-it';
|
|
2
|
+
const OPEN = 0x5b; // '['
|
|
3
|
+
/**
|
|
4
|
+
* local-browsing-surface design.md D3: a resolvable `[[Target]]` becomes a
|
|
5
|
+
* real link to that note's route; an unresolved or ambiguous one becomes
|
|
6
|
+
* visibly-marked, non-clickable markup naming the reason — never a link to
|
|
7
|
+
* an arbitrary or wrong target. Target extraction (up to the first `]`,
|
|
8
|
+
* `|`, or `#`) mirrors `extractLinks`' `WIKILINK_RE` in
|
|
9
|
+
* `src/core/graph/model.ts`, so a link this parses is a link the graph
|
|
10
|
+
* build parses identically.
|
|
11
|
+
*/
|
|
12
|
+
function wikilinkRule(state, silent) {
|
|
13
|
+
const start = state.pos;
|
|
14
|
+
const max = state.posMax;
|
|
15
|
+
if (start + 3 >= max)
|
|
16
|
+
return false;
|
|
17
|
+
if (state.src.charCodeAt(start) !== OPEN || state.src.charCodeAt(start + 1) !== OPEN)
|
|
18
|
+
return false;
|
|
19
|
+
const end = state.src.indexOf(']]', start + 2);
|
|
20
|
+
if (end === -1 || end > max)
|
|
21
|
+
return false;
|
|
22
|
+
const rawInner = state.src.slice(start + 2, end);
|
|
23
|
+
const targetMatch = /^([^\]|#]+)/.exec(rawInner);
|
|
24
|
+
const target = targetMatch?.[1]?.trim();
|
|
25
|
+
if (!target)
|
|
26
|
+
return false;
|
|
27
|
+
const pipeIdx = rawInner.indexOf('|');
|
|
28
|
+
const label = (pipeIdx !== -1 ? rawInner.slice(pipeIdx + 1).trim() : '') || target;
|
|
29
|
+
if (!silent) {
|
|
30
|
+
const token = state.push('wikilink', '', 0);
|
|
31
|
+
token.meta = { target, label };
|
|
32
|
+
}
|
|
33
|
+
state.pos = end + 2;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
export function escapeHtml(text) {
|
|
37
|
+
return text
|
|
38
|
+
.replace(/&/g, '&')
|
|
39
|
+
.replace(/</g, '<')
|
|
40
|
+
.replace(/>/g, '>')
|
|
41
|
+
.replace(/"/g, '"');
|
|
42
|
+
}
|
|
43
|
+
function renderWikilink(resolveLink) {
|
|
44
|
+
return (tokens, idx) => {
|
|
45
|
+
const { target, label } = tokens[idx].meta;
|
|
46
|
+
const resolution = resolveLink(target);
|
|
47
|
+
const safeLabel = escapeHtml(label);
|
|
48
|
+
if ('path' in resolution) {
|
|
49
|
+
return `<a href="/notes/${encodeURI(resolution.path)}">${safeLabel}</a>`;
|
|
50
|
+
}
|
|
51
|
+
const reasonText = resolution.reason === 'ambiguous' ? 'ambiguous' : 'unresolved';
|
|
52
|
+
const title = `${reasonText} wikilink target: ${target}`;
|
|
53
|
+
return `<span class="ctxr-broken-link" data-reason="${resolution.reason}" title="${escapeHtml(title)}">${safeLabel}</span>`;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function buildRenderer(resolveLink) {
|
|
57
|
+
const md = new MarkdownIt({ html: false, linkify: true });
|
|
58
|
+
md.inline.ruler.before('link', 'wikilink', wikilinkRule);
|
|
59
|
+
md.renderer.rules.wikilink = renderWikilink(resolveLink);
|
|
60
|
+
return md;
|
|
61
|
+
}
|
|
62
|
+
/** Renders a note's markdown body to HTML, with wikilinks resolved via `resolveLink` (design.md D3). */
|
|
63
|
+
export function renderNoteBody(body, resolveLink) {
|
|
64
|
+
return buildRenderer(resolveLink).render(body);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/core/browse/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Note } from '../notes/list.js';
|
|
2
|
+
import type { Store } from '../store.js';
|
|
3
|
+
export interface CatalogRoute {
|
|
4
|
+
id: string;
|
|
5
|
+
absolutePath: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PublishFileRoute {
|
|
8
|
+
/** URL-relative path under /publish/, e.g. "my-page/index.html". */
|
|
9
|
+
urlPath: string;
|
|
10
|
+
absolutePath: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RouteTable {
|
|
13
|
+
/** Keyed by store-relative note path (the same string used as the note's URL and its graph node id). */
|
|
14
|
+
notes: ReadonlyMap<string, Note>;
|
|
15
|
+
/** Keyed by catalog section id. */
|
|
16
|
+
catalog: ReadonlyMap<string, CatalogRoute>;
|
|
17
|
+
graphDocumentPath: string;
|
|
18
|
+
/** Keyed by the exact URL-relative path under /publish/ — a lookup miss is the only traversal guard needed (design.md D2). */
|
|
19
|
+
publishFiles: ReadonlyMap<string, PublishFileRoute>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* local-browsing-surface design.md D2: built fresh from the store's own
|
|
23
|
+
* enumeration on every call, never cached — so a path outside every
|
|
24
|
+
* configured location is absent from the table by construction, and a
|
|
25
|
+
* request for it is an ordinary lookup miss rather than a check that could
|
|
26
|
+
* be forgotten on one route and not another.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildRouteTable(store: Store): Promise<RouteTable>;
|
|
29
|
+
/** The distinct top-level page folders under the publish route, for the index page. */
|
|
30
|
+
export declare function publishSlugs(table: RouteTable): string[];
|
|
31
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/core/browse/routes.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,wGAAwG;IACxG,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,mCAAmC;IACnC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC3C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8HAA8H;IAC9H,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CACrD;AAuBD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,CAevE;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAOxD"}
|