@opum-ai/lore 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/bin/lore.cjs +109 -0
  4. package/package.json +67 -0
  5. package/src/adapters/backlog.ts +1084 -0
  6. package/src/adapters/git.ts +221 -0
  7. package/src/cli.ts +667 -0
  8. package/src/commands/agent.ts +301 -0
  9. package/src/commands/agents.ts +302 -0
  10. package/src/commands/args.ts +209 -0
  11. package/src/commands/changed.ts +70 -0
  12. package/src/commands/check.ts +1031 -0
  13. package/src/commands/codex-bridge.ts +49 -0
  14. package/src/commands/concurrency.ts +48 -0
  15. package/src/commands/context.ts +292 -0
  16. package/src/commands/discover.ts +89 -0
  17. package/src/commands/explorer.ts +253 -0
  18. package/src/commands/export.ts +93 -0
  19. package/src/commands/fswrite.ts +928 -0
  20. package/src/commands/graph.ts +291 -0
  21. package/src/commands/help.ts +151 -0
  22. package/src/commands/impact.ts +59 -0
  23. package/src/commands/init.ts +583 -0
  24. package/src/commands/instructions.ts +91 -0
  25. package/src/commands/link.ts +929 -0
  26. package/src/commands/new.ts +476 -0
  27. package/src/commands/orphans.ts +457 -0
  28. package/src/commands/path.ts +67 -0
  29. package/src/commands/provenance.ts +68 -0
  30. package/src/commands/query.ts +312 -0
  31. package/src/commands/reconcile-shared.ts +280 -0
  32. package/src/commands/rename.ts +585 -0
  33. package/src/commands/replace.ts +320 -0
  34. package/src/commands/scaffold.ts +346 -0
  35. package/src/commands/schema.ts +293 -0
  36. package/src/commands/snapshot.ts +130 -0
  37. package/src/commands/supersede.ts +400 -0
  38. package/src/commands/sync.ts +371 -0
  39. package/src/commands/tasks.ts +271 -0
  40. package/src/commands/traversal.ts +151 -0
  41. package/src/commands/validate.ts +226 -0
  42. package/src/config.ts +598 -0
  43. package/src/core/agent-bridge.ts +287 -0
  44. package/src/core/agent-context.ts +498 -0
  45. package/src/core/agent-profile.ts +447 -0
  46. package/src/core/bundle.ts +893 -0
  47. package/src/core/check.ts +853 -0
  48. package/src/core/codex-bridge.ts +100 -0
  49. package/src/core/concept.ts +597 -0
  50. package/src/core/consumer-scaffold.ts +433 -0
  51. package/src/core/context.ts +271 -0
  52. package/src/core/explorer-contract.ts +441 -0
  53. package/src/core/explorer-qualification.ts +58 -0
  54. package/src/core/explorer.ts +518 -0
  55. package/src/core/finding.ts +31 -0
  56. package/src/core/graph.ts +201 -0
  57. package/src/core/indexes.ts +436 -0
  58. package/src/core/instructions.ts +209 -0
  59. package/src/core/ladybug-driver.ts +1795 -0
  60. package/src/core/ladybug-lifecycle.ts +1178 -0
  61. package/src/core/ladybug-native.ts +95 -0
  62. package/src/core/ladybug-source.ts +667 -0
  63. package/src/core/links.ts +681 -0
  64. package/src/core/log.ts +253 -0
  65. package/src/core/managed-block.ts +540 -0
  66. package/src/core/manifest.ts +718 -0
  67. package/src/core/order.ts +13 -0
  68. package/src/core/profile.ts +1007 -0
  69. package/src/core/projection.ts +195 -0
  70. package/src/core/query.ts +542 -0
  71. package/src/core/reconcile.ts +236 -0
  72. package/src/core/replace.ts +419 -0
  73. package/src/core/retrieval.ts +213 -0
  74. package/src/core/rewrite.ts +940 -0
  75. package/src/core/scaffold.ts +255 -0
  76. package/src/core/schema.ts +366 -0
  77. package/src/core/snapshot-runtime.ts +52 -0
  78. package/src/core/snapshot-store.ts +287 -0
  79. package/src/core/snapshot.ts +711 -0
  80. package/src/core/template.ts +429 -0
  81. package/src/core/traversal.ts +487 -0
  82. package/src/core/validate.ts +517 -0
  83. package/src/core/workspace-contract.ts +473 -0
  84. package/src/core/workspace-projection.ts +365 -0
  85. package/src/core/workspace-retrieval.ts +196 -0
  86. package/src/core/workspace-source.ts +174 -0
  87. package/src/errors.ts +697 -0
  88. package/src/meta.ts +7 -0
  89. package/src/output.ts +589 -0
  90. package/src/scripts/upstream-backlog-watch.ts +288 -0
  91. package/src/state.ts +390 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jeremy Newhouse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,306 @@
1
+ # lore
2
+
3
+ > A thin, OKF-native documentation CLI that couples repo-resident docs to
4
+ > Backlog.md and serves them to coding agents and humans — CLI-first.
5
+
6
+ `lore` makes your repository's `docs/` tree a first-class, agent-readable
7
+ [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf)
8
+ (OKF v0.1) bundle, couples that bundle to [Backlog.md](https://github.com/MrLesk/Backlog.md)
9
+ tasks, and exposes it through a deterministic, non-interactive CLI. The
10
+ repository is the single source of truth — the bundle is plain markdown with
11
+ YAML frontmatter that renders on GitHub, in Obsidian, and under
12
+ MkDocs/Docusaurus, with or without `lore` installed.
13
+
14
+ `lore` is **thin** and **zero-config** by design. It does not reimplement
15
+ Backlog.md, Confluence, or the documentation consumers it scaffolds for. Its
16
+ core is **deterministic with no LLM dependency** — every command is
17
+ reproducible, idempotent, and CI/agent-safe (non-interactive by default, stable
18
+ semantic exit codes, machine-readable `--json`).
19
+
20
+ - Built on **Bun + TypeScript** with an exact-pinned **Commander** parser fed by
21
+ Lore's capability manifest; Lore still owns output, errors, and process lifecycle.
22
+ - Prepared for npm distribution as **`@opum-ai/lore@0.1.0`** (bin `lore`);
23
+ registry publication is not claimed until the release-truth evidence lands.
24
+ - The agent bridge is a generated **`.claude/skills/lore/SKILL.md`** plus a tiny
25
+ CLAUDE.md nudge and `lore instructions`. An **MCP server is secondary and
26
+ deferred to v2**.
27
+
28
+ > **Status: prepared 0.1.0 release candidate.** The six manifests and exact
29
+ > optional-dependency pins are set to `0.1.0`, but the repository has no
30
+ > release tag or artifact and `@opum-ai/lore` is absent from npm. The upstream
31
+ > Backlog.md dependency gate is complete
32
+ > (LCLI-253), but the repository-owner publication-control gate remains open
33
+ > (LCLI-278). See [Lore CLI release truth](docs/reference/lore-cli-release-truth.md).
34
+
35
+ ---
36
+
37
+ ## The headline: lore reads Backlog.md via JSON
38
+
39
+ `lore` couples docs to tasks by reading Backlog.md's **JSON** output — not by
40
+ scraping text and not by importing Backlog.md internals or hand-editing its task
41
+ files. It parses a canonical `{schemaVersion, kind, data}` envelope from
42
+ `backlog task list --json`, `backlog task view --json`, and `backlog search
43
+ --json`. There is **no `--plain` text-parser fallback** — that is a deliberate
44
+ decision to keep the coupling robust.
45
+
46
+ Backlog.md did not originally ship this JSON surface. It merged upstream in
47
+ MrLesk/Backlog.md as PR #790 and shipped in the v1.49.0 tagged release
48
+ (2026-08-02). `lore` has no package or git dependency on Backlog.md and invokes
49
+ the user-installed `backlog` executable (>=1.49.0) on `PATH`. A capability
50
+ probe enforces the JSON contract and **fails loud** when the installed binary
51
+ cannot provide it.
52
+
53
+ See the runbook: [Backlog.md `--json` patch](docs/runbooks/backlog-json-patch.md).
54
+
55
+ Coexistence rules `lore` follows so it never fights Backlog.md:
56
+
57
+ - Writes go through `backlog task create` / `backlog task edit` — `lore` captures
58
+ the new id from the `Created task <ID>` line and **never** writes
59
+ `backlog/tasks/*.md` directly.
60
+ - Back-references live on the task as a queryable label `doc:<conceptId>`
61
+ (Backlog drops unknown frontmatter on edit, so `lore` never stores its own
62
+ metadata on tasks).
63
+ - Backlog runs with `auto_commit=false`; `lore` is the **sole committer** of
64
+ `backlog/` (it does the `git add`/`commit` of task files itself), with
65
+ `check_active_branches=false` and `remote_operations=false`.
66
+
67
+ Full details: [Backlog CLI contract](docs/reference/backlog-cli-contract.md) and
68
+ [Backlog JSON schema](docs/reference/backlog-json-schema.md).
69
+
70
+ ---
71
+
72
+ ## Install
73
+
74
+ `@opum-ai/lore` is not published. Until the release-truth evidence is
75
+ complete, use a trusted source checkout and its pinned toolchain; do not expect
76
+ these planned registry commands to work.
77
+
78
+ After a verified release, the intended package and bin are
79
+ `@opum-ai/lore` and `lore`:
80
+
81
+ ```bash
82
+ # Node / npm
83
+ npx @opum-ai/lore --help
84
+
85
+ # Bun
86
+ bunx @opum-ai/lore --help
87
+ ```
88
+
89
+ Or add it to a project:
90
+
91
+ ```bash
92
+ bun add -d @opum-ai/lore # or: npm i -D @opum-ai/lore
93
+ ```
94
+
95
+ The planned npm package is a dual artifact: a Node `.cjs` launcher plus a
96
+ per-platform compiled binary delivered as `optionalDependencies` (built with
97
+ `bun build --compile`, `-baseline` x64 targets). You also need a
98
+ `--json`-capable Backlog.md (>=1.49.0) on `PATH` — e.g. `npm install -g
99
+ backlog.md`; see the [runbook](docs/runbooks/backlog-json-patch.md).
100
+
101
+ ### Private-repository CI before npm publication
102
+
103
+ Repositories inside the `opum-ai` organization can run strict Lore gates
104
+ without a cross-repository PAT or a public npm release:
105
+
106
+ ```yaml
107
+ - uses: actions/checkout@v6
108
+ - uses: opum-ai/lore-cli/.github/actions/strict-check@<full-commit-sha>
109
+ ```
110
+
111
+ The private composite action installs Bun 1.2.23 and this action revision's
112
+ frozen dependencies, installs the published JSON-capable `backlog.md` version
113
+ pinned by the Docker E2E harness, then runs `lore validate --strict` and `lore
114
+ check --strict` against the caller workspace. Consumer workflows must replace
115
+ the placeholder with the full immutable commit SHA. Private-action access
116
+ remains limited to organization repositories.
117
+
118
+ ---
119
+
120
+ ## Quickstart (CLI-first)
121
+
122
+ Every command is idempotent and emits stable exit codes. All of them are
123
+ non-interactive by default — the one exception is `lore init`, which runs a
124
+ guided wizard on a bare, interactive-terminal invocation (detecting and offering
125
+ Claude Code and Codex agent bridges, downstream doc-site scaffolds, and a backlog
126
+ capability check); it is strictly TTY-gated, so a non-TTY stdin or stderr,
127
+ `--json`, or any of its own flags runs it fully non-interactively too — see
128
+ [ADR-0017](docs/adr/0017-interactive-init-wizard-tty-gated.md). Output has
129
+ three modes with precedence `--json` > `--plain` > pretty:
130
+
131
+ - **pretty** — default; color on a TTY, honoring `NO_COLOR`.
132
+ - **`--plain`** — ANSI-free, stable text; the automatic mode when stdout is not
133
+ a TTY (pipes, CI, agents).
134
+ - **`--json`** — a `{schemaVersion, kind, data}` envelope on stdout; errors go to
135
+ stderr as `{error_type, message, hint, input}`.
136
+
137
+ ```bash
138
+ # 1. Scaffold the OKF bundle (docs/, .lore/, root index.md). On a bare TTY
139
+ # invocation this runs a guided wizard for the rest of onboarding too
140
+ # (agent bridge, doc-site scaffolds, backlog check); off a TTY (CI, this
141
+ # snippet) it's exactly this — the bundle only, non-interactively.
142
+ lore init
143
+
144
+ # 2. Create typed concepts from frontmatter templates.
145
+ lore new story "Bulk archive completed orders"
146
+ lore new spec "Order archival" --story stories/bulk-archive-completed-orders
147
+ lore new adr "Use soft deletes"
148
+
149
+ # 3. Couple a story to Backlog.md tasks (writes frontmatter + a doc:<id> label).
150
+ lore link stories/bulk-archive-completed-orders task-42 task-57
151
+
152
+ # 4. Reconcile status and rewrite the managed task block from live JSON.
153
+ lore sync
154
+
155
+ # 5. CI gate: report drift / broken links / portability issues (no writes).
156
+ lore check
157
+
158
+ # 6. Retrieve: full-text search and deterministic graph-context export.
159
+ lore query "archive retention" --type story
160
+ lore context stories/bulk-archive-completed-orders --max-tokens 4000
161
+ ```
162
+
163
+ `--plain` is stable, line-oriented text — ideal for pipes and grep:
164
+
165
+ ```bash
166
+ $ lore tasks stories/bulk-archive-completed-orders --plain
167
+ task-42 Bulk archive Done
168
+ task-57 Archive UI In Progress
169
+ ```
170
+
171
+ `--json` is the additive-only machine contract:
172
+
173
+ ```bash
174
+ $ lore check --json
175
+ {
176
+ "schemaVersion": "1",
177
+ "kind": "check.report",
178
+ "data": {
179
+ "ok": false,
180
+ "drift": [
181
+ { "concept": "stories/bulk-archive-completed-orders",
182
+ "field": "status", "have": "todo", "want": "in-progress" }
183
+ ],
184
+ "brokenLinks": [],
185
+ "portability": []
186
+ }
187
+ }
188
+ ```
189
+
190
+ ```bash
191
+ $ lore validate --json && echo "conformant" # exit 6 on validation/drift
192
+ ```
193
+
194
+ Semantic exit codes (uniform across commands): `0` ok, `2` usage, `3`
195
+ not-found, `4` denied, `5` conflict/exists, `6` validation-or-drift. See the
196
+ [CLI contract](docs/reference/cli-contract.md) for the full output and exit-code
197
+ spec, and the [CLI surface](docs/reference/cli-surface.md) for every command and
198
+ flag.
199
+
200
+ ### Refactoring and navigation
201
+
202
+ ```bash
203
+ lore graph --json # cross-link graph + token estimates
204
+ lore graph --dot # Graphviz DOT
205
+ lore export > lore-projection.jsonl # full consumer-neutral OKF/task projection
206
+ lore orphans # tasks with no owning doc; docs whose tasks vanished
207
+ lore replace "OldName" "NewName" --in 'reference/**' --dry-run
208
+ lore rename reference/orders reference/order-lines # graph-aware: rewrites inbound links
209
+ lore supersede adr/0004-foo adr/0009-bar # sets superseded_by/supersedes/status
210
+ ```
211
+
212
+ `replace` skips `lore`-managed regions; `rename`/`supersede` use the bundle
213
+ graph to rewrite all inbound links and frontmatter refs.
214
+
215
+ ---
216
+
217
+ ## How coding agents use lore
218
+
219
+ `lore` is CLI-first for humans **and** agents. Its agent bridges are generated,
220
+ not bespoke:
221
+
222
+ - `lore agents` emits `.claude/skills/lore/SKILL.md` — a skill that teaches
223
+ Claude Code when and how to drive `lore` (always with `--json` for
224
+ structured results).
225
+ - `lore init --codex` emits `.codex/skills/lore/SKILL.md`; a managed block in
226
+ `AGENTS.md` points Codex at that skill without overwriting repository guidance.
227
+ - A tiny managed block in `CLAUDE.md` points Claude Code at its skill.
228
+ - `lore instructions` prints task-shaped guidance on demand for any agent or
229
+ human.
230
+
231
+ An agent's typical loop: read `lore context <id> --json` to pull a concept plus
232
+ 1-line neighbor summaries within a token budget, do the work, then run
233
+ `lore sync` and `lore check --json` to keep docs coherent — all deterministic,
234
+ all without an LLM in `lore`'s core.
235
+
236
+ See [Agent onboarding](docs/runbooks/agent-onboarding.md).
237
+
238
+ ---
239
+
240
+ ## One bundle, many consumers
241
+
242
+ `docs/` is a valid OKF v0.1 bundle on its own. To keep it portable across
243
+ renderers, every cross-link is **relative, URL-encoded, `.md`-suffixed, with no
244
+ leading slash and no wikilinks** — the only form that resolves identically on
245
+ **GitHub**, in **Obsidian** (graph + backlinks), under **MkDocs**, and under
246
+ **Docusaurus**. `lore`'s portability lint warns on non-portable syntax.
247
+
248
+ `lore scaffold` writes consumer configs **additively, outside `docs/`** so the
249
+ bundle stays clean:
250
+
251
+ ```bash
252
+ lore scaffold mkdocs # mkdocs.yml
253
+ lore scaffold docusaurus # docusaurus.config + markdown.format:'detect'
254
+ lore scaffold obsidian # .obsidian/ vault config
255
+ ```
256
+
257
+ A **one-way Confluence publish** adapter (Cloud/ADF) is planned as an isolated
258
+ module with zero core dependency, but its **implementation is deferred**
259
+ (Server/DC is deferred-not-dropped). See
260
+ [Consumer compatibility](docs/reference/consumer-compatibility.md) and
261
+ [Portable Markdown](docs/reference/portable-markdown.md).
262
+
263
+ ---
264
+
265
+ ## Roadmap
266
+
267
+ Tracked as Backlog.md milestones, built in order:
268
+
269
+ | Milestone | Scope |
270
+ |---|---|
271
+ | **BJP** | Upstream stable JSON for Backlog.md reads (completed in PR #790; tagged-release adoption gates lore 0.1) |
272
+ | **M0** | Foundations: repo, runtime pin, build/distribution skeleton |
273
+ | **M1** | Core + scaffolding: `init`, `new`, `validate`, concept/frontmatter lib (gray-matter + Zod), bundle walk |
274
+ | **M2** | Backlog coupling: `link`, `sync`, `check`, managed block (remark), status reconciliation |
275
+ | **M3** | Navigability, search & refactoring: `graph`, `orphans`, `query`, `context`, `replace`, `rename`, `supersede` |
276
+ | **M4** | Agent bridge: generated `SKILL.md`, CLAUDE.md nudge, `lore instructions` |
277
+ | **M5** | Browsable + graph consumers: `lore scaffold` for MkDocs/Docusaurus/Obsidian |
278
+ | _M6 (deferred)_ | MCP server — same core functions over a deferred transport |
279
+ | _M7–M8 (deferred)_ | Confluence: one-way publish, then mirror |
280
+
281
+ ---
282
+
283
+ ## Documentation
284
+
285
+ The full design lives in this repo's OKF bundle under [`docs/`](docs/index.md):
286
+
287
+ - [Documentation index](docs/index.md) — the OKF root and reading hub.
288
+ - [Architecture](docs/reference/architecture.md) — the deterministic-core /
289
+ thin-transport shape.
290
+ - [lore design spec](docs/specs/lore-design.md) — the end-to-end design.
291
+ - [CLI surface](docs/reference/cli-surface.md) and
292
+ [CLI contract](docs/reference/cli-contract.md).
293
+ - [ADRs](docs/adr/index.md) — the significant, hard-to-reverse decisions.
294
+ - [MCP tools (deferred)](docs/reference/mcp-tools.md) — the v2 MCP design.
295
+
296
+ ---
297
+
298
+ ## Contributing
299
+
300
+ This is a private repo (`main` + `dev`; `dev` is the default branch). See
301
+ [CONTRIBUTING](CONTRIBUTING.md), the [Code of Conduct](CODE_OF_CONDUCT.md), and
302
+ [SECURITY](SECURITY.md).
303
+
304
+ ## License
305
+
306
+ [MIT](LICENSE) © 2026 Jeremy Newhouse.
package/bin/lore.cjs ADDED
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ /**
5
+ * bin/lore.cjs — the published package's future `bin` entry (ADR-0001 §"Distribution", LORE-9).
6
+ *
7
+ * This is the ONLY file that runs under plain Node rather than Bun: it is what makes
8
+ * `npx @opum-ai/lore` / a global `npm install -g` work for a user who has Node
9
+ * but not Bun. Its entire job is to locate the compiled binary for the current
10
+ * platform (installed as one of the package's `optionalDependencies`, gated by npm's
11
+ * `os`/`cpu` fields so only the matching one lands in `node_modules`) and exec it,
12
+ * forwarding argv/stdio/exit code verbatim.
13
+ *
14
+ * NOT YET the active `bin` target: `package.json`'s `bin.lore` still points at
15
+ * `src/cli.ts` (the pre-publish install path — git dependency, `npm`/`bun link`), because
16
+ * this file only works once the five platform packages it resolves are actually published.
17
+ * Flipping `bin.lore` to this file is the first step of cutting a real release, not a
18
+ * standing state — see docs/runbooks/release-publishing.md.
19
+ *
20
+ * Kept deliberately tiny and dependency-free plain CommonJS (`.cjs`, so it runs as
21
+ * CJS regardless of the package's own `"type": "module"`) — per ADR-0001, "the
22
+ * launcher must stay plain, dependency-light, Node-compatible CJS: it cannot use
23
+ * Bun-only APIs." All of lore's actual logic lives in the compiled binary; this file
24
+ * never imports `src/`.
25
+ */
26
+
27
+ const { spawnSync } = require("node:child_process");
28
+ const os = require("node:os");
29
+ const path = require("node:path");
30
+
31
+ /** The compiled binary's name inside its platform package (`.exe` on Windows). */
32
+ const BINARY_NAME = process.platform === "win32" ? "lore.exe" : "lore";
33
+
34
+ /**
35
+ * The `optionalDependencies` package name for the current platform, matching
36
+ * `process.platform`/`process.arch` directly (`darwin-arm64`, `linux-x64`, …) so the
37
+ * mapping needs no lookup table — it must stay byte-identical to the `npm/<name>/`
38
+ * directories this repo publishes from and to `package.json`'s `optionalDependencies`.
39
+ */
40
+ function platformPackageName() {
41
+ return `@opum-ai/lore-${process.platform}-${process.arch}`;
42
+ }
43
+
44
+ /**
45
+ * Resolve the absolute path to the current platform's compiled binary, or `null` when its
46
+ * optional package genuinely never installed (npm skips `optionalDependencies` whose `os`/`cpu`
47
+ * don't match the host). Only `require.resolve`'s own `MODULE_NOT_FOUND` is treated as "not
48
+ * installed" — any other thrown error (a permission error reading the package directory, a
49
+ * corrupted install, `ERR_PACKAGE_PATH_NOT_EXPORTED`, …) propagates to the caller instead of
50
+ * being silently folded into the same "unsupported platform" message, which would misdirect a
51
+ * user with a real, fixable install problem.
52
+ */
53
+ function resolveBinaryPath() {
54
+ const pkgName = platformPackageName();
55
+ let pkgJsonPath;
56
+ try {
57
+ pkgJsonPath = require.resolve(`${pkgName}/package.json`);
58
+ } catch (err) {
59
+ if (err && err.code === "MODULE_NOT_FOUND") {
60
+ return null;
61
+ }
62
+ throw err;
63
+ }
64
+ return path.join(path.dirname(pkgJsonPath), "bin", BINARY_NAME);
65
+ }
66
+
67
+ /**
68
+ * The exit code to forward for a `spawnSync` result with no exit `status` (i.e. the child was
69
+ * terminated by a signal, `result.signal` set). Uses the conventional `128 + signal number`
70
+ * (matching a POSIX shell) so a caller inspecting `$?` — e.g. to tell a user's Ctrl-C (SIGINT,
71
+ * conventionally 130) apart from a genuine tool failure — sees the real signal, not a generic 1.
72
+ * Falls back to `1` only if the signal name is somehow unrecognized (`os.constants.signals` has
73
+ * no entry for it), which should not happen for any signal Node itself can report.
74
+ */
75
+ function exitCodeForSignal(signal) {
76
+ const signalNumber = os.constants.signals[signal];
77
+ return signalNumber === undefined ? 1 : 128 + signalNumber;
78
+ }
79
+
80
+ function main() {
81
+ let binaryPath;
82
+ try {
83
+ binaryPath = resolveBinaryPath();
84
+ } catch (err) {
85
+ process.stderr.write(
86
+ `lore: unexpected error resolving the compiled binary for ${platformPackageName()}: ${err.message}\n`,
87
+ );
88
+ process.exit(1);
89
+ }
90
+ if (binaryPath === null) {
91
+ process.stderr.write(
92
+ `lore: no compiled binary found for this platform (${process.platform}-${process.arch}).\n` +
93
+ `Expected the optional dependency "${platformPackageName()}" to be installed alongside\n` +
94
+ `@opum-ai/lore, but it is missing. If your platform/architecture is one lore\n` +
95
+ `ships (macOS x64/arm64, Linux x64/arm64, Windows x64), try reinstalling with npm;\n` +
96
+ `otherwise this platform is not yet supported.\n`,
97
+ );
98
+ process.exit(1);
99
+ }
100
+
101
+ const result = spawnSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
102
+ if (result.error) {
103
+ process.stderr.write(`lore: failed to run the compiled binary at ${binaryPath}: ${result.error.message}\n`);
104
+ process.exit(1);
105
+ }
106
+ process.exit(result.status === null ? exitCodeForSignal(result.signal) : result.status);
107
+ }
108
+
109
+ main();
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@opum-ai/lore",
3
+ "version": "0.1.0",
4
+ "description": "Thin, OKF-native documentation CLI that couples repo-resident docs to Backlog.md and serves them to agents and humans.",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "module": "src/cli.ts",
10
+ "bin": {
11
+ "lore": "bin/lore.cjs"
12
+ },
13
+ "license": "MIT",
14
+ "author": "Jeremy Newhouse",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/opum-ai/lore-cli.git"
18
+ },
19
+ "packageManager": "bun@1.2.23",
20
+ "engines": {
21
+ "bun": ">=1.2.23"
22
+ },
23
+ "files": [
24
+ "src",
25
+ "bin",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "optionalDependencies": {
30
+ "@opum-ai/lore-darwin-arm64": "0.1.0",
31
+ "@opum-ai/lore-darwin-x64": "0.1.0",
32
+ "@opum-ai/lore-linux-arm64": "0.1.0",
33
+ "@opum-ai/lore-linux-x64": "0.1.0",
34
+ "@opum-ai/lore-win32-x64": "0.1.0"
35
+ },
36
+ "scripts": {
37
+ "lore": "bun run src/cli.ts",
38
+ "build": "bun build --compile src/cli.ts --outfile dist/lore",
39
+ "typecheck": "tsc --noEmit",
40
+ "format": "biome format --write .",
41
+ "lint": "biome check .",
42
+ "lint:fix": "biome check --write .",
43
+ "test": "bun test",
44
+ "test:browser": "playwright test",
45
+ "test:coverage": "bun test --coverage"
46
+ },
47
+ "devDependencies": {
48
+ "@biomejs/biome": "2.4.12",
49
+ "@playwright/test": "1.62.1",
50
+ "@types/bun": "^1.2.23",
51
+ "@types/mdast": "4.0.4",
52
+ "typescript": "^5"
53
+ },
54
+ "dependencies": {
55
+ "@ladybugdb/core": "0.19.0",
56
+ "commander": "15.0.0",
57
+ "github-slugger": "2.0.0",
58
+ "ipaddr.js": "2.4.0",
59
+ "js-yaml": "5.2.2",
60
+ "mdast-util-from-markdown": "2.0.3",
61
+ "string-width": "8.2.2",
62
+ "zod": "4.4.3"
63
+ },
64
+ "trustedDependencies": [
65
+ "@ladybugdb/core"
66
+ ]
67
+ }