baselane 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 +191 -0
- package/README.md +40 -0
- package/bin/baselane.mjs +44 -0
- package/dist/apply.d.ts +16 -0
- package/dist/apply.js +103 -0
- package/dist/audit.d.ts +8 -0
- package/dist/audit.js +30 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +2 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +231 -0
- package/dist/draft-pack.d.ts +3 -0
- package/dist/draft-pack.js +22 -0
- package/dist/drift-cmd.d.ts +28 -0
- package/dist/drift-cmd.js +98 -0
- package/dist/graph.d.ts +10 -0
- package/dist/graph.js +44 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/install.d.ts +4 -0
- package/dist/install.js +12 -0
- package/dist/map.d.ts +15 -0
- package/dist/map.js +63 -0
- package/dist/publish.d.ts +27 -0
- package/dist/publish.js +76 -0
- package/dist/report.d.ts +7 -0
- package/dist/report.js +13 -0
- package/dist/update.d.ts +25 -0
- package/dist/update.js +84 -0
- package/package.json +53 -0
package/dist/report.d.ts
ADDED
package/dist/report.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export async function reportAdoption(portalUrl, token, record, fetchImpl = fetch) {
|
|
2
|
+
const base = portalUrl.endsWith("/") ? portalUrl.slice(0, -1) : portalUrl;
|
|
3
|
+
const res = await fetchImpl(`${base}/api/adoption`, {
|
|
4
|
+
method: "POST",
|
|
5
|
+
headers: {
|
|
6
|
+
authorization: `Bearer ${token}`,
|
|
7
|
+
"content-type": "application/json",
|
|
8
|
+
},
|
|
9
|
+
body: JSON.stringify({ ...record, status: "proposed" }),
|
|
10
|
+
});
|
|
11
|
+
if (!res.ok)
|
|
12
|
+
throw new Error(`portal adoption report failed: ${res.status}`);
|
|
13
|
+
}
|
package/dist/update.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type InstallReport } from "./install.ts";
|
|
2
|
+
export interface UpdateOptions {
|
|
3
|
+
name?: string;
|
|
4
|
+
global: boolean;
|
|
5
|
+
dir?: string;
|
|
6
|
+
homeDir?: string;
|
|
7
|
+
dryRun: boolean;
|
|
8
|
+
token?: string;
|
|
9
|
+
fetchImpl?: typeof fetch;
|
|
10
|
+
registryBase?: string;
|
|
11
|
+
log?: (line: string) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface UpdateReport {
|
|
14
|
+
changed: Array<{
|
|
15
|
+
name: string;
|
|
16
|
+
ref: string;
|
|
17
|
+
oldSha: string | null;
|
|
18
|
+
newSha: string;
|
|
19
|
+
}>;
|
|
20
|
+
/** Registry packs whose "is a newer version published" check failed (registry unreachable,
|
|
21
|
+
* malformed response, etc) this run — left pinned at their current version, not a crash. */
|
|
22
|
+
skippedRegistry: string[];
|
|
23
|
+
install: InstallReport;
|
|
24
|
+
}
|
|
25
|
+
export declare function runUpdate(opts: UpdateOptions): Promise<UpdateReport>;
|
package/dist/update.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { isGitSourceName } from "@baselane/distribute";
|
|
2
|
+
import { DEFAULT_REGISTRY, decodeSkillPin, fetchRegistryVersions, readManifestWithFallback, resolveManifestPacks, targetLocation, writeManifestFile, } from "@baselane/materialize";
|
|
3
|
+
import { runInstall } from "./install.js";
|
|
4
|
+
// `install` alone would also re-resolve moving refs (a moved tag or branch pin is exactly what
|
|
5
|
+
// re-resolution is for); update's added value is named scoping, the old→new sha report, and (for
|
|
6
|
+
// registry packs) finding+writing a newer EXACT version pin before that re-resolution runs.
|
|
7
|
+
//
|
|
8
|
+
// KNOWN LIMITATION (M2a, documented not fixed): `--name` scoping affects only the report below —
|
|
9
|
+
// `runInstall` re-resolves every pack in the manifest regardless, since install is whole-manifest
|
|
10
|
+
// by design.
|
|
11
|
+
export async function runUpdate(opts) {
|
|
12
|
+
const log = opts.log ?? console.log;
|
|
13
|
+
const loc = targetLocation({ global: opts.global, dir: opts.dir, homeDir: opts.homeDir });
|
|
14
|
+
const { manifest } = await readManifestWithFallback(loc);
|
|
15
|
+
if (manifest === null)
|
|
16
|
+
throw new Error(`update: no harness.json at ${loc.manifestPath} — run baselane install first`);
|
|
17
|
+
const gitNames = Object.keys(manifest.packs).filter(isGitSourceName);
|
|
18
|
+
const registryNames = Object.keys(manifest.packs).filter((n) => !isGitSourceName(n));
|
|
19
|
+
const allNames = [...gitNames, ...registryNames];
|
|
20
|
+
if (opts.name !== undefined && !allNames.includes(opts.name)) {
|
|
21
|
+
throw new Error(`update: "${opts.name}" is not a pack in this manifest — packs: ${allNames.join(", ") || "(none)"}`);
|
|
22
|
+
}
|
|
23
|
+
// Registry packs are exact-pin-only: unlike a git ref (a branch/tag name whose pin never
|
|
24
|
+
// changes — only the sha it resolves to moves), "update" for a registry pack means finding a
|
|
25
|
+
// NEWER version and rewriting the pin itself. A registry that's unreachable for this check is a
|
|
26
|
+
// per-pack warning, not a fatal error — the pack just stays pinned where it was.
|
|
27
|
+
const registryTargets = opts.name !== undefined ? registryNames.filter((n) => n === opts.name) : registryNames;
|
|
28
|
+
const registryBase = manifest.registry ?? opts.registryBase ?? DEFAULT_REGISTRY;
|
|
29
|
+
const bumpedPacks = { ...manifest.packs };
|
|
30
|
+
const skippedRegistry = [];
|
|
31
|
+
for (const name of registryTargets) {
|
|
32
|
+
try {
|
|
33
|
+
const versions = await fetchRegistryVersions(name, registryBase, { fetchImpl: opts.fetchImpl });
|
|
34
|
+
const latest = versions[0]?.version;
|
|
35
|
+
if (latest !== undefined && latest !== manifest.packs[name])
|
|
36
|
+
bumpedPacks[name] = latest;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
skippedRegistry.push(name);
|
|
40
|
+
log(`update: "${name}" registry lookup failed (${err instanceof Error ? err.message : String(err)}) — leaving pinned at ${manifest.packs[name]}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const bumped = JSON.stringify(bumpedPacks) !== JSON.stringify(manifest.packs);
|
|
44
|
+
const manifestForResolve = bumped ? { ...manifest, packs: bumpedPacks } : manifest;
|
|
45
|
+
if (!opts.dryRun && bumped)
|
|
46
|
+
await writeManifestFile(loc.manifestPath, manifestForResolve);
|
|
47
|
+
const oldResolutions = manifest.materialized.resolutions;
|
|
48
|
+
const install = await runInstall({
|
|
49
|
+
global: opts.global, dir: opts.dir, homeDir: opts.homeDir,
|
|
50
|
+
dryRun: opts.dryRun, json: false, token: opts.token, fetchImpl: opts.fetchImpl, registryBase: opts.registryBase, log,
|
|
51
|
+
});
|
|
52
|
+
const targets = opts.name !== undefined ? [opts.name] : allNames;
|
|
53
|
+
// dry-run never wrote a new manifest — resolve fresh shas in-memory instead of reading disk, so
|
|
54
|
+
// the preview still reports a moved tag/branch (or a bumped registry version) instead of always
|
|
55
|
+
// claiming "unchanged".
|
|
56
|
+
let newResolutions;
|
|
57
|
+
if (opts.dryRun) {
|
|
58
|
+
const fresh = await resolveManifestPacks(manifestForResolve, { token: opts.token, fetchImpl: opts.fetchImpl, registryBase: opts.registryBase });
|
|
59
|
+
newResolutions = fresh.resolutions;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const { manifest: updated } = await readManifestWithFallback(loc);
|
|
63
|
+
newResolutions = updated?.materialized.resolutions ?? null;
|
|
64
|
+
}
|
|
65
|
+
const changed = [];
|
|
66
|
+
for (const name of targets) {
|
|
67
|
+
const oldSha = oldResolutions[name]?.sha ?? null;
|
|
68
|
+
const newSha = newResolutions?.[name]?.sha ?? oldSha ?? "";
|
|
69
|
+
const ref = bumpedPacks[name] ?? manifest.packs[name];
|
|
70
|
+
// A skill-scoped git pack encodes the onlySkill filter behind a control-character separator
|
|
71
|
+
// (see encodeSkillPin) — decode before logging, same as formatInstallReport, or the raw
|
|
72
|
+
// U+0001 byte prints straight to the terminal.
|
|
73
|
+
const { ref: shownRef, onlySkill } = decodeSkillPin(ref);
|
|
74
|
+
const shownRefLabel = `${shownRef}${onlySkill ? ` (skill: ${onlySkill})` : ""}`;
|
|
75
|
+
if (newSha !== "" && newSha !== oldSha) {
|
|
76
|
+
changed.push({ name, ref, oldSha, newSha });
|
|
77
|
+
log(`updated ${name}: ${shownRefLabel} ${oldSha?.slice(0, 7) ?? "(none)"} → ${newSha.slice(0, 7)}`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
log(`unchanged ${name}@${shownRefLabel}${oldSha ? ` (${oldSha.slice(0, 7)})` : ""}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { changed, skippedRegistry, install };
|
|
84
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "baselane",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Git-native package manager for AI coding harnesses — audit a repo, apply workflow packs, and keep agent config in sync.",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"baselane": "./bin/baselane.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=24"
|
|
12
|
+
},
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/mohammad0omar/baselane.sh.git"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://baselane.sh",
|
|
19
|
+
"keywords": [
|
|
20
|
+
"ai",
|
|
21
|
+
"agents",
|
|
22
|
+
"skills",
|
|
23
|
+
"claude",
|
|
24
|
+
"harness",
|
|
25
|
+
"package-manager",
|
|
26
|
+
"cli",
|
|
27
|
+
"workflow",
|
|
28
|
+
"agent-config"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"bin/",
|
|
32
|
+
"dist/",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@baselane/analyze": "0.1.0",
|
|
37
|
+
"@baselane/distribute": "0.1.0",
|
|
38
|
+
"@baselane/packs": "0.1.0",
|
|
39
|
+
"@baselane/materialize": "0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^24.0.0",
|
|
43
|
+
"typescript": "^5.9.0",
|
|
44
|
+
"vitest": "^2.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"cli": "node --experimental-transform-types --no-warnings src/bin.ts",
|
|
50
|
+
"build": "tsc -p tsconfig.build.json"
|
|
51
|
+
},
|
|
52
|
+
"types": "./dist/index.d.ts"
|
|
53
|
+
}
|