@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.
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/bin/lore.cjs +109 -0
- package/package.json +67 -0
- package/src/adapters/backlog.ts +1084 -0
- package/src/adapters/git.ts +221 -0
- package/src/cli.ts +667 -0
- package/src/commands/agent.ts +301 -0
- package/src/commands/agents.ts +302 -0
- package/src/commands/args.ts +209 -0
- package/src/commands/changed.ts +70 -0
- package/src/commands/check.ts +1031 -0
- package/src/commands/codex-bridge.ts +49 -0
- package/src/commands/concurrency.ts +48 -0
- package/src/commands/context.ts +292 -0
- package/src/commands/discover.ts +89 -0
- package/src/commands/explorer.ts +253 -0
- package/src/commands/export.ts +93 -0
- package/src/commands/fswrite.ts +928 -0
- package/src/commands/graph.ts +291 -0
- package/src/commands/help.ts +151 -0
- package/src/commands/impact.ts +59 -0
- package/src/commands/init.ts +583 -0
- package/src/commands/instructions.ts +91 -0
- package/src/commands/link.ts +929 -0
- package/src/commands/new.ts +476 -0
- package/src/commands/orphans.ts +457 -0
- package/src/commands/path.ts +67 -0
- package/src/commands/provenance.ts +68 -0
- package/src/commands/query.ts +312 -0
- package/src/commands/reconcile-shared.ts +280 -0
- package/src/commands/rename.ts +585 -0
- package/src/commands/replace.ts +320 -0
- package/src/commands/scaffold.ts +346 -0
- package/src/commands/schema.ts +293 -0
- package/src/commands/snapshot.ts +130 -0
- package/src/commands/supersede.ts +400 -0
- package/src/commands/sync.ts +371 -0
- package/src/commands/tasks.ts +271 -0
- package/src/commands/traversal.ts +151 -0
- package/src/commands/validate.ts +226 -0
- package/src/config.ts +598 -0
- package/src/core/agent-bridge.ts +287 -0
- package/src/core/agent-context.ts +498 -0
- package/src/core/agent-profile.ts +447 -0
- package/src/core/bundle.ts +893 -0
- package/src/core/check.ts +853 -0
- package/src/core/codex-bridge.ts +100 -0
- package/src/core/concept.ts +597 -0
- package/src/core/consumer-scaffold.ts +433 -0
- package/src/core/context.ts +271 -0
- package/src/core/explorer-contract.ts +441 -0
- package/src/core/explorer-qualification.ts +58 -0
- package/src/core/explorer.ts +518 -0
- package/src/core/finding.ts +31 -0
- package/src/core/graph.ts +201 -0
- package/src/core/indexes.ts +436 -0
- package/src/core/instructions.ts +209 -0
- package/src/core/ladybug-driver.ts +1795 -0
- package/src/core/ladybug-lifecycle.ts +1178 -0
- package/src/core/ladybug-native.ts +95 -0
- package/src/core/ladybug-source.ts +667 -0
- package/src/core/links.ts +681 -0
- package/src/core/log.ts +253 -0
- package/src/core/managed-block.ts +540 -0
- package/src/core/manifest.ts +718 -0
- package/src/core/order.ts +13 -0
- package/src/core/profile.ts +1007 -0
- package/src/core/projection.ts +195 -0
- package/src/core/query.ts +542 -0
- package/src/core/reconcile.ts +236 -0
- package/src/core/replace.ts +419 -0
- package/src/core/retrieval.ts +213 -0
- package/src/core/rewrite.ts +940 -0
- package/src/core/scaffold.ts +255 -0
- package/src/core/schema.ts +366 -0
- package/src/core/snapshot-runtime.ts +52 -0
- package/src/core/snapshot-store.ts +287 -0
- package/src/core/snapshot.ts +711 -0
- package/src/core/template.ts +429 -0
- package/src/core/traversal.ts +487 -0
- package/src/core/validate.ts +517 -0
- package/src/core/workspace-contract.ts +473 -0
- package/src/core/workspace-projection.ts +365 -0
- package/src/core/workspace-retrieval.ts +196 -0
- package/src/core/workspace-source.ts +174 -0
- package/src/errors.ts +697 -0
- package/src/meta.ts +7 -0
- package/src/output.ts +589 -0
- package/src/scripts/upstream-backlog-watch.ts +288 -0
- 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
|
+
}
|