@opum-ai/lore 0.1.0 → 0.2.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 (90) hide show
  1. package/README.md +33 -22
  2. package/bin/lore.cjs +35 -7
  3. package/package.json +17 -17
  4. package/src/adapters/backlog.ts +0 -1084
  5. package/src/adapters/git.ts +0 -221
  6. package/src/cli.ts +0 -667
  7. package/src/commands/agent.ts +0 -301
  8. package/src/commands/agents.ts +0 -302
  9. package/src/commands/args.ts +0 -209
  10. package/src/commands/changed.ts +0 -70
  11. package/src/commands/check.ts +0 -1031
  12. package/src/commands/codex-bridge.ts +0 -49
  13. package/src/commands/concurrency.ts +0 -48
  14. package/src/commands/context.ts +0 -292
  15. package/src/commands/discover.ts +0 -89
  16. package/src/commands/explorer.ts +0 -253
  17. package/src/commands/export.ts +0 -93
  18. package/src/commands/fswrite.ts +0 -928
  19. package/src/commands/graph.ts +0 -291
  20. package/src/commands/help.ts +0 -151
  21. package/src/commands/impact.ts +0 -59
  22. package/src/commands/init.ts +0 -583
  23. package/src/commands/instructions.ts +0 -91
  24. package/src/commands/link.ts +0 -929
  25. package/src/commands/new.ts +0 -476
  26. package/src/commands/orphans.ts +0 -457
  27. package/src/commands/path.ts +0 -67
  28. package/src/commands/provenance.ts +0 -68
  29. package/src/commands/query.ts +0 -312
  30. package/src/commands/reconcile-shared.ts +0 -280
  31. package/src/commands/rename.ts +0 -585
  32. package/src/commands/replace.ts +0 -320
  33. package/src/commands/scaffold.ts +0 -346
  34. package/src/commands/schema.ts +0 -293
  35. package/src/commands/snapshot.ts +0 -130
  36. package/src/commands/supersede.ts +0 -400
  37. package/src/commands/sync.ts +0 -371
  38. package/src/commands/tasks.ts +0 -271
  39. package/src/commands/traversal.ts +0 -151
  40. package/src/commands/validate.ts +0 -226
  41. package/src/config.ts +0 -598
  42. package/src/core/agent-bridge.ts +0 -287
  43. package/src/core/agent-context.ts +0 -498
  44. package/src/core/agent-profile.ts +0 -447
  45. package/src/core/bundle.ts +0 -893
  46. package/src/core/check.ts +0 -853
  47. package/src/core/codex-bridge.ts +0 -100
  48. package/src/core/concept.ts +0 -597
  49. package/src/core/consumer-scaffold.ts +0 -433
  50. package/src/core/context.ts +0 -271
  51. package/src/core/explorer-contract.ts +0 -441
  52. package/src/core/explorer-qualification.ts +0 -58
  53. package/src/core/explorer.ts +0 -518
  54. package/src/core/finding.ts +0 -31
  55. package/src/core/graph.ts +0 -201
  56. package/src/core/indexes.ts +0 -436
  57. package/src/core/instructions.ts +0 -209
  58. package/src/core/ladybug-driver.ts +0 -1795
  59. package/src/core/ladybug-lifecycle.ts +0 -1178
  60. package/src/core/ladybug-native.ts +0 -95
  61. package/src/core/ladybug-source.ts +0 -667
  62. package/src/core/links.ts +0 -681
  63. package/src/core/log.ts +0 -253
  64. package/src/core/managed-block.ts +0 -540
  65. package/src/core/manifest.ts +0 -718
  66. package/src/core/order.ts +0 -13
  67. package/src/core/profile.ts +0 -1007
  68. package/src/core/projection.ts +0 -195
  69. package/src/core/query.ts +0 -542
  70. package/src/core/reconcile.ts +0 -236
  71. package/src/core/replace.ts +0 -419
  72. package/src/core/retrieval.ts +0 -213
  73. package/src/core/rewrite.ts +0 -940
  74. package/src/core/scaffold.ts +0 -255
  75. package/src/core/schema.ts +0 -366
  76. package/src/core/snapshot-runtime.ts +0 -52
  77. package/src/core/snapshot-store.ts +0 -287
  78. package/src/core/snapshot.ts +0 -711
  79. package/src/core/template.ts +0 -429
  80. package/src/core/traversal.ts +0 -487
  81. package/src/core/validate.ts +0 -517
  82. package/src/core/workspace-contract.ts +0 -473
  83. package/src/core/workspace-projection.ts +0 -365
  84. package/src/core/workspace-retrieval.ts +0 -196
  85. package/src/core/workspace-source.ts +0 -174
  86. package/src/errors.ts +0 -697
  87. package/src/meta.ts +0 -7
  88. package/src/output.ts +0 -589
  89. package/src/scripts/upstream-backlog-watch.ts +0 -288
  90. package/src/state.ts +0 -390
@@ -1,288 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * upstream-backlog-watch.ts — LORE-254.
4
- *
5
- * Repo-maintenance script, **not** part of the `lore` CLI surface (no `--json` envelope, no
6
- * exit-code contract, not reachable through `lore <command>` at all). It is invoked directly by
7
- * `.github/workflows/upstream-backlog-watch.yml` on a schedule.
8
- *
9
- * Why this exists: MrLesk/Backlog.md merged commit 22a091b (PR #790 / BACK-545, stable `--json`
10
- * output on `task list`/`task view`/`search`) to `main` on 2026-07-16, but has not yet **tagged**
11
- * a release that contains it (the latest tag as of writing, v1.48.0, predates the merge). LORE-253
12
- * — the adapter migration that unblocks lore's own first npm release — is blocked on that tag
13
- * existing, and nothing upstream notifies lore when it ships. This script polls MrLesk/Backlog.md's
14
- * Releases API and, the first time it finds a release whose commit history actually **contains**
15
- * 22a091b (not merely a release numbered higher than v1.48.0 — a newer tag could still predate the
16
- * merge), opens a tracking issue in THIS repo labeled `upstream-watch` so the maintainer can pick up
17
- * LORE-253. See `docs/runbooks/upstream-backlog-md-json-tag-watch.md` for the full runbook (where the signal
18
- * lands, who acts on it) and `docs/runbooks/backlog-json-patch.md` §8.1 for what LORE-253 does once
19
- * unblocked.
20
- *
21
- * Kept stateless by design: rather than persisting "already scanned up to tag X", it re-derives
22
- * "already surfaced" by asking GitHub whether a tracking issue carrying TRACKING_LABEL already
23
- * exists (open OR closed) before doing any upstream work. Once a qualifying release is found and
24
- * reported once, every later upstream release also contains 22a091b in its history forever after
25
- * (commits don't leave history) — so the existing-issue check is what stops this from re-notifying
26
- * on every future upstream release, not a per-tag dedupe.
27
- */
28
-
29
- const UPSTREAM_REPO = "MrLesk/Backlog.md";
30
- const TARGET_COMMIT = "22a091b570d44c4f302ca47e7fd36fa28ad8bcb0";
31
- const TARGET_COMMIT_PR_URL = "https://github.com/MrLesk/Backlog.md/pull/790";
32
- // PR #790 merged 2026-07-16 (docs/runbooks/backlog-json-patch.md §8.1) -- any release published
33
- // strictly before this cannot possibly contain the commit, so it bounds the scan to real
34
- // candidates instead of walking MrLesk/Backlog.md's entire release history on every run.
35
- const TARGET_COMMIT_MERGED_AT = "2026-07-16T00:00:00Z";
36
- export const TRACKING_LABEL = "upstream-watch";
37
- const TRACKING_LABEL_COLOR = "6f42c1";
38
- const TRACKING_LABEL_DESCRIPTION = "MrLesk/Backlog.md shipped a --json-capable tag (LORE-254); see the linked issue.";
39
-
40
- export interface ReleaseInfo {
41
- tagName: string;
42
- publishedAt: string;
43
- }
44
-
45
- export interface QualifyingRelease {
46
- tagName: string;
47
- sha: string;
48
- }
49
-
50
- export type WatchResult =
51
- | { action: "already-surfaced" }
52
- | { action: "no-match" }
53
- | { action: "opened"; tagName: string; issueUrl: string };
54
-
55
- /**
56
- * Keep only releases that could possibly contain {@link TARGET_COMMIT}: everything published
57
- * at/after {@link TARGET_COMMIT_MERGED_AT}. GitHub's Releases API list order is `created_at` desc
58
- * (not guaranteed `published_at` order — a release drafted before the cutoff but published after
59
- * it can sort below an older-published release), so this is a plain filter rather than a
60
- * newest-first prefix-take: the list is already capped at `per_page=100` in memory, so a full
61
- * scan costs nothing extra and doesn't risk silently dropping a qualifying release.
62
- */
63
- export function candidateReleases(releases: ReleaseInfo[], cutoffIso: string = TARGET_COMMIT_MERGED_AT): ReleaseInfo[] {
64
- return releases.filter((release) => release.publishedAt >= cutoffIso);
65
- }
66
-
67
- /**
68
- * GitHub's compare API (`/compare/{base}...{head}`) `status` field: `"identical"` or `"ahead"`
69
- * (head ahead of base) both mean `base` is an ancestor of (or equal to) `head` — i.e. the tag's
70
- * history actually contains the commit. This is what distinguishes a real `--json`-capable tag
71
- * from one that is merely numbered newer (`"behind"` / `"diverged"`).
72
- */
73
- export function isAncestorCompareStatus(status: string): boolean {
74
- return status === "identical" || status === "ahead";
75
- }
76
-
77
- /** The tracking issue body for a release confirmed to contain {@link TARGET_COMMIT}. */
78
- export function renderIssueBody(release: QualifyingRelease): string {
79
- const releaseUrl = `https://github.com/${UPSTREAM_REPO}/releases/tag/${release.tagName}`;
80
- return [
81
- `MrLesk/Backlog.md tag [\`${release.tagName}\`](${releaseUrl}) (commit \`${release.sha}\`) is the first`,
82
- `tagged release whose history contains commit \`${TARGET_COMMIT}\``,
83
- `([PR #790](${TARGET_COMMIT_PR_URL}) / BACK-545 — stable \`--json\` output on \`task list\`/\`task view\`/\`search\`),`,
84
- "confirmed via the GitHub compare API (not merely a tag numbered newer than v1.48.0).",
85
- "",
86
- 'This is the external event **LORE-253** ("Migrate backlog adapter to the released --json',
87
- "Backlog.md...\") and `docs/runbooks/release-publishing.md`'s release Prerequisites were both",
88
- "waiting on — it is also the last gate on lore's own first npm release.",
89
- "",
90
- "**Next step:** `backlog task view LORE-253 --plain`, then follow",
91
- "`docs/runbooks/backlog-json-patch.md` §8.1 step 4 to point `src/adapters/backlog.ts` at the",
92
- "published package instead of the interim pinned-commit build.",
93
- "",
94
- "Detected by `.github/workflows/upstream-backlog-watch.yml` (LORE-254); see",
95
- "`docs/runbooks/upstream-backlog-md-json-tag-watch.md` for how this signal works and who acts on it.",
96
- ].join("\n");
97
- }
98
-
99
- // ── I/O boundary ─────────────────────────────────────────────────────────────
100
- // Everything below talks to the GitHub REST API. Every function threads through an injectable
101
- // `fetcher` (defaulting to the real global `fetch` only at the `watchOnce` boundary) so the whole
102
- // orchestration can be exercised in tests against a stub instead of the network.
103
-
104
- type Fetcher = typeof fetch;
105
-
106
- class GithubApiError extends Error {
107
- constructor(
108
- method: string,
109
- url: string,
110
- readonly status: number,
111
- body: string,
112
- ) {
113
- super(`GitHub API ${method} ${url} -> ${status}: ${body}`);
114
- }
115
- }
116
-
117
- async function githubApi<T>(fetcher: Fetcher, token: string, method: string, path: string, body?: unknown): Promise<T> {
118
- const url = path.startsWith("http") ? path : `https://api.github.com${path}`;
119
- const response = await fetcher(url, {
120
- method,
121
- headers: {
122
- Accept: "application/vnd.github+json",
123
- Authorization: `Bearer ${token}`,
124
- "X-GitHub-Api-Version": "2022-11-28",
125
- "User-Agent": "lore-upstream-backlog-watch (LORE-254)",
126
- ...(body !== undefined ? { "Content-Type": "application/json" } : {}),
127
- },
128
- body: body !== undefined ? JSON.stringify(body) : undefined,
129
- });
130
- if (!response.ok) {
131
- throw new GithubApiError(method, url, response.status, await response.text());
132
- }
133
- return (await response.json()) as T;
134
- }
135
-
136
- interface UpstreamReleaseApiRow {
137
- tag_name: string;
138
- published_at: string | null;
139
- draft: boolean;
140
- }
141
-
142
- async function listUpstreamReleases(fetcher: Fetcher, token: string): Promise<ReleaseInfo[]> {
143
- const rows = await githubApi<UpstreamReleaseApiRow[]>(
144
- fetcher,
145
- token,
146
- "GET",
147
- `/repos/${UPSTREAM_REPO}/releases?per_page=100`,
148
- );
149
- return rows
150
- .filter((row): row is UpstreamReleaseApiRow & { published_at: string } => !row.draft && row.published_at !== null)
151
- .map((row) => ({ tagName: row.tag_name, publishedAt: row.published_at }));
152
- }
153
-
154
- async function resolveTagSha(fetcher: Fetcher, token: string, tag: string): Promise<string> {
155
- const commit = await githubApi<{ sha: string }>(fetcher, token, "GET", `/repos/${UPSTREAM_REPO}/commits/${tag}`);
156
- return commit.sha;
157
- }
158
-
159
- async function compareAgainstTarget(fetcher: Fetcher, token: string, sha: string): Promise<string> {
160
- const comparison = await githubApi<{ status: string }>(
161
- fetcher,
162
- token,
163
- "GET",
164
- `/repos/${UPSTREAM_REPO}/compare/${TARGET_COMMIT}...${sha}`,
165
- );
166
- return comparison.status;
167
- }
168
-
169
- /**
170
- * The first candidate release, in GitHub's Releases API list order (`created_at` desc — not
171
- * necessarily `published_at` order), whose history contains {@link TARGET_COMMIT}, if any.
172
- */
173
- async function findQualifyingRelease(fetcher: Fetcher, token: string): Promise<QualifyingRelease | null> {
174
- const releases = await listUpstreamReleases(fetcher, token);
175
- for (const candidate of candidateReleases(releases)) {
176
- const sha = await resolveTagSha(fetcher, token, candidate.tagName);
177
- const status = await compareAgainstTarget(fetcher, token, sha);
178
- if (isAncestorCompareStatus(status)) {
179
- return { tagName: candidate.tagName, sha };
180
- }
181
- }
182
- return null;
183
- }
184
-
185
- interface OwnIssueApiRow {
186
- pull_request?: unknown;
187
- }
188
-
189
- async function trackingIssueAlreadyExists(fetcher: Fetcher, token: string, repoSlug: string): Promise<boolean> {
190
- const rows = await githubApi<OwnIssueApiRow[]>(
191
- fetcher,
192
- token,
193
- "GET",
194
- `/repos/${repoSlug}/issues?labels=${TRACKING_LABEL}&state=all&per_page=100`,
195
- );
196
- // The issues endpoint also returns pull requests carrying the label; a real hit must be an
197
- // actual issue.
198
- return rows.some((row) => !row.pull_request);
199
- }
200
-
201
- async function ensureTrackingLabelExists(fetcher: Fetcher, token: string, repoSlug: string): Promise<void> {
202
- try {
203
- await githubApi(fetcher, token, "POST", `/repos/${repoSlug}/labels`, {
204
- name: TRACKING_LABEL,
205
- color: TRACKING_LABEL_COLOR,
206
- description: TRACKING_LABEL_DESCRIPTION,
207
- });
208
- } catch (error) {
209
- // 422 = the label already exists; anything else is a real failure.
210
- if (!(error instanceof GithubApiError && error.status === 422)) {
211
- throw error;
212
- }
213
- }
214
- }
215
-
216
- interface CreatedIssueApiRow {
217
- html_url: string;
218
- }
219
-
220
- async function openTrackingIssue(
221
- fetcher: Fetcher,
222
- token: string,
223
- repoSlug: string,
224
- release: QualifyingRelease,
225
- ): Promise<string> {
226
- const created = await githubApi<CreatedIssueApiRow>(fetcher, token, "POST", `/repos/${repoSlug}/issues`, {
227
- title: `Upstream Backlog.md ${release.tagName} is --json-capable — LORE-253 is unblocked`,
228
- body: renderIssueBody(release),
229
- labels: [TRACKING_LABEL],
230
- });
231
- return created.html_url;
232
- }
233
-
234
- /**
235
- * Run one check: skip entirely if already surfaced, otherwise probe upstream and open the
236
- * tracking issue on a hit. `fetcher` defaults to the real global `fetch` — tests pass a stub.
237
- */
238
- export async function watchOnce(
239
- env: { repoSlug: string; token: string },
240
- fetcher: Fetcher = fetch,
241
- ): Promise<WatchResult> {
242
- if (await trackingIssueAlreadyExists(fetcher, env.token, env.repoSlug)) {
243
- return { action: "already-surfaced" };
244
- }
245
- const found = await findQualifyingRelease(fetcher, env.token);
246
- if (!found) {
247
- return { action: "no-match" };
248
- }
249
- await ensureTrackingLabelExists(fetcher, env.token, env.repoSlug);
250
- const issueUrl = await openTrackingIssue(fetcher, env.token, env.repoSlug, found);
251
- return { action: "opened", tagName: found.tagName, issueUrl };
252
- }
253
-
254
- async function main(): Promise<number> {
255
- const repoSlug = process.env.GITHUB_REPOSITORY;
256
- const token = process.env.GITHUB_TOKEN;
257
- if (!repoSlug || !token) {
258
- console.error("GITHUB_REPOSITORY and GITHUB_TOKEN must both be set (this script runs under GitHub Actions).");
259
- return 1;
260
- }
261
- const result = await watchOnce({ repoSlug, token });
262
- switch (result.action) {
263
- case "already-surfaced":
264
- console.log(`A "${TRACKING_LABEL}" tracking issue already exists in ${repoSlug}; nothing to do.`);
265
- break;
266
- case "no-match":
267
- console.log(`No MrLesk/Backlog.md release yet contains ${TARGET_COMMIT}.`);
268
- break;
269
- case "opened":
270
- console.log(`Opened ${result.issueUrl} for upstream tag ${result.tagName}.`);
271
- break;
272
- }
273
- return 0;
274
- }
275
-
276
- // Same shape as cli.ts's own entrypoint guard (LORE-70): set `process.exitCode` rather than call
277
- // `process.exit()` so pending stdout/stderr writes flush before the process actually ends.
278
- if (import.meta.main) {
279
- Promise.resolve(main()).then(
280
- (code) => {
281
- process.exitCode = code;
282
- },
283
- (error) => {
284
- console.error(error);
285
- process.exitCode = 1;
286
- },
287
- );
288
- }