@cairn-tool/cairn 4.1.0 → 5.0.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/README.md +24 -11
- package/dist/agent/marketplace/index.d.ts +14 -2
- package/dist/agent/marketplace/index.js +57 -13
- package/dist/agent/marketplace/index.js.map +1 -1
- package/dist/agent/marketplace/layout.d.ts +48 -0
- package/dist/agent/marketplace/layout.js +71 -0
- package/dist/agent/marketplace/layout.js.map +1 -0
- package/dist/agent/marketplace/release-manifest.d.ts +87 -0
- package/dist/agent/marketplace/release-manifest.js +88 -0
- package/dist/agent/marketplace/release-manifest.js.map +1 -0
- package/dist/agent/marketplace/release-readme.d.ts +12 -0
- package/dist/agent/marketplace/release-readme.js +73 -0
- package/dist/agent/marketplace/release-readme.js.map +1 -0
- package/dist/agent/marketplace/source-bundles.d.ts +46 -0
- package/dist/agent/marketplace/source-bundles.js +133 -0
- package/dist/agent/marketplace/source-bundles.js.map +1 -0
- package/dist/agent/parser.js +15 -4
- package/dist/agent/parser.js.map +1 -1
- package/dist/agent/types.d.ts +29 -0
- package/dist/agent/types.js.map +1 -1
- package/dist/cli.js +8 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/agent-marketplace.d.ts +5 -0
- package/dist/commands/agent-marketplace.js +31 -6
- package/dist/commands/agent-marketplace.js.map +1 -1
- package/dist/contract/registry.js +1 -1
- package/dist/contract/registry.js.map +1 -1
- package/dist/contract/schemas/qa.js +4 -4
- package/dist/contract/schemas/qa.js.map +1 -1
- package/dist/qa/agents/codex.d.ts +8 -0
- package/dist/qa/agents/codex.js +192 -0
- package/dist/qa/agents/codex.js.map +1 -0
- package/dist/qa/agents/index.d.ts +4 -4
- package/dist/qa/agents/index.js +7 -5
- package/dist/qa/agents/index.js.map +1 -1
- package/dist/qa/agents/types.d.ts +4 -0
- package/dist/qa/agents/types.js.map +1 -1
- package/dist/qa/cases.d.ts +3 -2
- package/dist/qa/cases.js +3 -2
- package/dist/qa/cases.js.map +1 -1
- package/dist/qa/slot.js +4 -0
- package/dist/qa/slot.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Eight toolsets, plus `describe`, `schema`, `serve`, `completion`, and `check-upd
|
|
|
69
69
|
| `archive` | Keep what a session produced before the logs are pruned, and get it back. | [Archiving](docs/guide/archiving.md) |
|
|
70
70
|
| `jira` | Convert Jira and Confluence rich text between ADF and Markdown. | [Jira rich text](docs/guide/jira.md) |
|
|
71
71
|
| `pdf` | Read PDF documents: text, structure, embedded files, and conversion to Markdown. | [PDF documents](docs/guide/pdf.md) |
|
|
72
|
-
| `qa` | Run TC-N test-case plans through Cursor
|
|
72
|
+
| `qa` | Run TC-N test-case plans through Cursor, Claude Code, and Codex backends. | [QA harness](docs/guide/qa.md) |
|
|
73
73
|
|
|
74
74
|
`scripts run` and `qa run` are the two commands that execute anything. `scripts run` only
|
|
75
75
|
runs what a tracked file in your repository names. `qa run` discovers `_plans/tc-N.yaml` and
|
|
@@ -97,22 +97,35 @@ Full documentation lives in
|
|
|
97
97
|
## Plugins
|
|
98
98
|
|
|
99
99
|
Cairn ships its own toolsets as installable plugins, so an assistant has the command surface
|
|
100
|
-
available without rediscovering it from `--help`.
|
|
101
|
-
|
|
100
|
+
available without rediscovering it from `--help`. Everything is published to a single `release`
|
|
101
|
+
branch, which carries each host's catalog at its own root path:
|
|
102
102
|
|
|
103
|
-
| Host |
|
|
104
|
-
| ----------- |
|
|
105
|
-
| Claude Code |
|
|
106
|
-
| Codex |
|
|
107
|
-
| Cursor |
|
|
103
|
+
| Host | Catalog | Install from |
|
|
104
|
+
| ----------- | ---------------------------------- | ------------------------------ |
|
|
105
|
+
| Claude Code | `.claude-plugin/marketplace.json` | the marketplace, or `bundles/` |
|
|
106
|
+
| Codex | `.agents/plugins/marketplace.json` | the marketplace, or `bundles/` |
|
|
107
|
+
| Cursor | `.cursor-plugin/marketplace.json` | the marketplace, or `bundles/` |
|
|
108
|
+
| Antigravity | none | `bundles/` |
|
|
108
109
|
|
|
109
110
|
The marketplace is named `cairn`, and the plugins in it are `cairn-markdown`, `cairn-scripts`,
|
|
110
111
|
`cairn-usage`, `cairn-archive`, `cairn-agent`, `cairn-jira`, `cairn-pdf`, and `cairn-qa`.
|
|
111
112
|
|
|
113
|
+
The branch also publishes the **source bundles** under `bundles/`, so a host with no marketplace
|
|
114
|
+
concept is installed straight off the same branch:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
git clone --branch release https://github.com/cairn-tool/cairn.git
|
|
118
|
+
cairn agent install cairn/bundles/cairn-markdown --target antigravity --scope user
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
> **Moved from the per-host branches.** `claude-plugins`, `codex-plugins` and `cursor-plugins` are
|
|
122
|
+
> replaced by `release`. A marketplace added from one of those must be removed and re-added — the
|
|
123
|
+
> marketplace key changed, and there is no in-place upgrade across that.
|
|
124
|
+
|
|
112
125
|
### Claude Code
|
|
113
126
|
|
|
114
127
|
```text
|
|
115
|
-
/plugin marketplace add cairn-tool/cairn@
|
|
128
|
+
/plugin marketplace add cairn-tool/cairn@release
|
|
116
129
|
/plugin install cairn-markdown@cairn
|
|
117
130
|
```
|
|
118
131
|
|
|
@@ -122,7 +135,7 @@ Add the branch as a marketplace, then install from it by name. `--ref` is what p
|
|
|
122
135
|
marketplace to the published branch rather than `main`:
|
|
123
136
|
|
|
124
137
|
```bash
|
|
125
|
-
codex plugin marketplace add cairn-tool/cairn --ref
|
|
138
|
+
codex plugin marketplace add cairn-tool/cairn --ref release
|
|
126
139
|
codex plugin add cairn-markdown@cairn
|
|
127
140
|
```
|
|
128
141
|
|
|
@@ -135,7 +148,7 @@ installs from is local, so it does not update on its own.
|
|
|
135
148
|
Cursor has no CLI for adding a marketplace; a repository-backed one is a **team marketplace**,
|
|
136
149
|
which is a Teams or Enterprise feature. In the dashboard, go to **Plugins → Team Marketplaces →
|
|
137
150
|
Add Marketplace → Import from Repo**, point it at `https://github.com/cairn-tool/cairn` and the
|
|
138
|
-
`
|
|
151
|
+
`release` branch, then install from **Customize** in the sidebar. Turning on **Auto
|
|
139
152
|
Refresh** re-reads the catalog whenever that branch is pushed.
|
|
140
153
|
|
|
141
154
|
Without a team plan, install locally instead — this drops the plugins into
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { AgentBundle, AgentDiagnostic, AgentTarget, Artifact } from "../types.js";
|
|
2
2
|
import type { PackageArchive } from "../package/index.js";
|
|
3
3
|
import type { MarketplaceSpec } from "./spec.js";
|
|
4
|
+
import type { CollectionLayout } from "./layout.js";
|
|
5
|
+
import type { PublishedBundle } from "./source-bundles.js";
|
|
4
6
|
export declare const MARKETPLACE_REPORT = "marketplace-report.json";
|
|
5
7
|
/**
|
|
6
8
|
* Distribution modes a collection supports.
|
|
@@ -27,7 +29,10 @@ export interface CollectionTarget {
|
|
|
27
29
|
export interface MarketplaceReport {
|
|
28
30
|
name: string;
|
|
29
31
|
version: string;
|
|
32
|
+
layout: CollectionLayout;
|
|
30
33
|
targets: CollectionTarget[];
|
|
34
|
+
/** Source bundles published alongside the rendered trees, in spec order. */
|
|
35
|
+
sources: PublishedBundle[];
|
|
31
36
|
archives: PackageArchive[];
|
|
32
37
|
checksums: string;
|
|
33
38
|
sbom: string;
|
|
@@ -64,6 +69,13 @@ export declare function collectionHasFindings(diagnostics: AgentDiagnostic[], st
|
|
|
64
69
|
*/
|
|
65
70
|
export declare function buildCollection(spec: MarketplaceSpec, targets: AgentTarget[], mode: CollectionMode, options?: {
|
|
66
71
|
archive?: boolean;
|
|
72
|
+
layout?: CollectionLayout;
|
|
73
|
+
/** Publish the source bundles. Defaults on under the release layout. */
|
|
74
|
+
sourceBundles?: boolean;
|
|
75
|
+
/** Version written into each published `agent-bundle.yaml`. */
|
|
76
|
+
stampVersion?: string;
|
|
77
|
+
/** Commit the published tree was built from, recorded in the manifest. */
|
|
78
|
+
sourceCommit?: string;
|
|
79
|
+
/** `owner/name` of the repository this is published from; generates README.md. */
|
|
80
|
+
readme?: string;
|
|
67
81
|
}): CollectionBuild;
|
|
68
|
-
/** Collection-relative directories the writer owns outright, one per target. */
|
|
69
|
-
export declare function managedRootsFor(targets: AgentTarget[]): string[];
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { diagnostic } from "../types.js";
|
|
3
2
|
import { loadBundle } from "../parser.js";
|
|
4
3
|
import { renderBundle } from "../render.js";
|
|
@@ -6,6 +5,11 @@ import { profileFor } from "../targets/index.js";
|
|
|
6
5
|
import { buildArchives, buildCatalogs, buildChecksums, buildSbom, checkAssets, checkCaseCollisions, checkExecutables, checkPinning, } from "../package/index.js";
|
|
7
6
|
import { TarPathTooLongError } from "../package/tar.js";
|
|
8
7
|
import { selectedForTarget } from "./spec.js";
|
|
8
|
+
import { catalogPathFor, sourceFor } from "./layout.js";
|
|
9
|
+
import { buildSourceBundles } from "./source-bundles.js";
|
|
10
|
+
import { buildReleaseManifest } from "./release-manifest.js";
|
|
11
|
+
import { buildReleaseReadme } from "./release-readme.js";
|
|
12
|
+
import { packageName, packageVersion } from "../../version.js";
|
|
9
13
|
export const MARKETPLACE_REPORT = "marketplace-report.json";
|
|
10
14
|
/**
|
|
11
15
|
* Distribution modes a collection supports.
|
|
@@ -53,10 +57,25 @@ function relocate(artifact, target, plugin) {
|
|
|
53
57
|
* per-target branching here.
|
|
54
58
|
*/
|
|
55
59
|
export function buildCollection(spec, targets, mode, options = {}) {
|
|
60
|
+
const layout = options.layout ?? "nested";
|
|
61
|
+
const withSources = options.sourceBundles ?? layout === "release";
|
|
56
62
|
const diagnostics = [];
|
|
57
63
|
const bundles = new Map();
|
|
58
64
|
for (const entry of spec.bundles)
|
|
59
65
|
bundles.set(entry.path, loadBundle(entry.root));
|
|
66
|
+
// Stamp before anything renders. The catalog's `version` is read off
|
|
67
|
+
// `manifest.version` while AB501 compares it against `bundle.version`, so both
|
|
68
|
+
// have to move together — and they have to move here, or the catalogs and the
|
|
69
|
+
// rendered plugin manifests would advertise a version the published source
|
|
70
|
+
// does not carry. Done on the loaded copy, never on the working tree, which is
|
|
71
|
+
// what makes the stamp-and-restore dance in a release script unnecessary.
|
|
72
|
+
if (options.stampVersion !== undefined)
|
|
73
|
+
for (const bundle of bundles.values()) {
|
|
74
|
+
if (bundle.version !== options.stampVersion)
|
|
75
|
+
diagnostics.push(diagnostic("AB912", `Stamped '${bundle.name}' from ${bundle.version} to ${options.stampVersion}`, "exact", { path: bundle.root }));
|
|
76
|
+
bundle.version = options.stampVersion;
|
|
77
|
+
bundle.manifest.version = options.stampVersion;
|
|
78
|
+
}
|
|
60
79
|
// Two bundles may declare distinct paths and still render the same plugin
|
|
61
80
|
// name, which a host would resolve arbitrarily.
|
|
62
81
|
const byName = new Map();
|
|
@@ -127,11 +146,8 @@ export function buildCollection(spec, targets, mode, options = {}) {
|
|
|
127
146
|
...(spec.description !== undefined ? { description: spec.description } : {}),
|
|
128
147
|
owner: spec.owner,
|
|
129
148
|
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// catalog shares a directory with the single plugin it describes.
|
|
133
|
-
sourceFor: (bundle) => `./${bundle.name}`,
|
|
134
|
-
catalogPathFor: (id, _profile, where) => `${id}/${where.directory}/${where.file}`,
|
|
149
|
+
sourceFor: (bundle) => sourceFor(layout, target, bundle.name),
|
|
150
|
+
catalogPathFor: (id, _profile, where) => catalogPathFor(layout, id, where),
|
|
135
151
|
attributeToBundle: true,
|
|
136
152
|
});
|
|
137
153
|
diagnostics.push(...catalogs.diagnostics);
|
|
@@ -144,10 +160,20 @@ export function buildCollection(spec, targets, mode, options = {}) {
|
|
|
144
160
|
artifacts.push(...targetArtifacts);
|
|
145
161
|
reportTargets.push({
|
|
146
162
|
target,
|
|
147
|
-
catalog: location ?
|
|
163
|
+
catalog: location ? catalogPathFor(layout, target, location) : null,
|
|
148
164
|
plugins,
|
|
149
165
|
});
|
|
150
166
|
}
|
|
167
|
+
// Before the payload is sorted and digested, so `checksums.sha256` and the
|
|
168
|
+
// sbom cover the sources too. A checksum file that omitted published files
|
|
169
|
+
// would be a lie about what the branch carries.
|
|
170
|
+
let sources = [];
|
|
171
|
+
if (withSources) {
|
|
172
|
+
const built = buildSourceBundles(spec.bundles, bundles);
|
|
173
|
+
artifacts.push(...built.artifacts);
|
|
174
|
+
diagnostics.push(...built.diagnostics);
|
|
175
|
+
sources = built.published;
|
|
176
|
+
}
|
|
151
177
|
const payload = sortByPath(artifacts);
|
|
152
178
|
diagnostics.push(...checkExecutables(payload), ...checkCaseCollisions(payload));
|
|
153
179
|
const extra = [];
|
|
@@ -180,7 +206,27 @@ export function buildCollection(spec, targets, mode, options = {}) {
|
|
|
180
206
|
});
|
|
181
207
|
}
|
|
182
208
|
}
|
|
183
|
-
|
|
209
|
+
// Built from `payload`, which already holds every rendered tree and every
|
|
210
|
+
// published source, and folded in before the checksums so the manifest is
|
|
211
|
+
// itself covered by them.
|
|
212
|
+
const manifest = [];
|
|
213
|
+
if (layout === "release") {
|
|
214
|
+
const document = buildReleaseManifest({
|
|
215
|
+
marketplace: spec.name,
|
|
216
|
+
version: options.stampVersion ?? spec.version,
|
|
217
|
+
...(spec.description !== undefined ? { description: spec.description } : {}),
|
|
218
|
+
...(options.sourceCommit !== undefined ? { sourceCommit: options.sourceCommit } : {}),
|
|
219
|
+
generator: { name: packageName, version: packageVersion },
|
|
220
|
+
targets: reportTargets,
|
|
221
|
+
sources,
|
|
222
|
+
descriptions: new Map([...bundles.values()].map((bundle) => [bundle.name, bundle.description])),
|
|
223
|
+
artifacts: payload,
|
|
224
|
+
});
|
|
225
|
+
manifest.push(document);
|
|
226
|
+
if (options.readme !== undefined)
|
|
227
|
+
manifest.push(buildReleaseReadme(JSON.parse(document.content.toString("utf8")), options.readme));
|
|
228
|
+
}
|
|
229
|
+
const withArchives = sortByPath([...payload, ...extra, ...manifest]);
|
|
184
230
|
const checksums = buildChecksums(withArchives);
|
|
185
231
|
// The sbom's subject is the collection, not any one bundle, so it is given a
|
|
186
232
|
// synthetic bundle carrying the spec's identity.
|
|
@@ -188,8 +234,10 @@ export function buildCollection(spec, targets, mode, options = {}) {
|
|
|
188
234
|
const sbom = buildSbom(subject, withArchives);
|
|
189
235
|
const report = {
|
|
190
236
|
name: spec.name,
|
|
191
|
-
version: spec.version,
|
|
237
|
+
version: options.stampVersion ?? spec.version,
|
|
238
|
+
layout,
|
|
192
239
|
targets: reportTargets,
|
|
240
|
+
sources,
|
|
193
241
|
archives,
|
|
194
242
|
checksums: checksums.path,
|
|
195
243
|
sbom: sbom.path,
|
|
@@ -205,8 +253,4 @@ export function buildCollection(spec, targets, mode, options = {}) {
|
|
|
205
253
|
bundles,
|
|
206
254
|
};
|
|
207
255
|
}
|
|
208
|
-
/** Collection-relative directories the writer owns outright, one per target. */
|
|
209
|
-
export function managedRootsFor(targets) {
|
|
210
|
-
return targets.map((target) => path.join(target));
|
|
211
|
-
}
|
|
212
256
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/marketplace/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/marketplace/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AgentTarget } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* How a built collection is arranged on disk.
|
|
4
|
+
*
|
|
5
|
+
* The two differ in exactly two values — where each target's catalog is written,
|
|
6
|
+
* and what its entries point at — so they live here together rather than as
|
|
7
|
+
* branches scattered through the builder.
|
|
8
|
+
*/
|
|
9
|
+
export declare const COLLECTION_LAYOUTS: readonly ["nested", "release"];
|
|
10
|
+
export type CollectionLayout = (typeof COLLECTION_LAYOUTS)[number];
|
|
11
|
+
/** A target profile's declared catalog location. */
|
|
12
|
+
export interface CatalogLocation {
|
|
13
|
+
directory: string;
|
|
14
|
+
file: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Where one target's aggregated catalog is written, relative to the collection
|
|
18
|
+
* root.
|
|
19
|
+
*
|
|
20
|
+
* `nested` gives every target its own subtree, which is what `--install` needs:
|
|
21
|
+
* it strips the `<target>/` prefix to get a host marketplace directory.
|
|
22
|
+
*
|
|
23
|
+
* `release` hoists every catalog to the shared root, which is what a *branch*
|
|
24
|
+
* needs: each host looks for its catalog at the repository root and nowhere
|
|
25
|
+
* else. The three hosts that declare one look in three different places
|
|
26
|
+
* (`.claude-plugin/`, `.cursor-plugin/`, `.agents/plugins/`), so they coexist
|
|
27
|
+
* there without collision, and one branch serves all of them.
|
|
28
|
+
*/
|
|
29
|
+
export declare function catalogPathFor(layout: CollectionLayout, target: AgentTarget, location: CatalogLocation): string;
|
|
30
|
+
/**
|
|
31
|
+
* The `source` a catalog entry carries, relative to the catalog itself.
|
|
32
|
+
*
|
|
33
|
+
* Never rewritten to `./`, which is only correct when a catalog shares a
|
|
34
|
+
* directory with the single plugin it describes.
|
|
35
|
+
*/
|
|
36
|
+
export declare function sourceFor(layout: CollectionLayout, target: AgentTarget, bundleName: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* What the writer owns in the output directory: directories it may clear
|
|
39
|
+
* wholesale, and files it owns individually.
|
|
40
|
+
*
|
|
41
|
+
* This is the one computation that must not be approximated. A root the writer
|
|
42
|
+
* does not know it owns keeps stale files across a release — a bundle dropped
|
|
43
|
+
* upstream would go on being published indefinitely.
|
|
44
|
+
*/
|
|
45
|
+
export declare function ownership(layout: CollectionLayout, targets: AgentTarget[], paths: string[]): {
|
|
46
|
+
managedRoots: string[];
|
|
47
|
+
looseFiles: string[];
|
|
48
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a built collection is arranged on disk.
|
|
3
|
+
*
|
|
4
|
+
* The two differ in exactly two values — where each target's catalog is written,
|
|
5
|
+
* and what its entries point at — so they live here together rather than as
|
|
6
|
+
* branches scattered through the builder.
|
|
7
|
+
*/
|
|
8
|
+
export const COLLECTION_LAYOUTS = ["nested", "release"];
|
|
9
|
+
/**
|
|
10
|
+
* Where one target's aggregated catalog is written, relative to the collection
|
|
11
|
+
* root.
|
|
12
|
+
*
|
|
13
|
+
* `nested` gives every target its own subtree, which is what `--install` needs:
|
|
14
|
+
* it strips the `<target>/` prefix to get a host marketplace directory.
|
|
15
|
+
*
|
|
16
|
+
* `release` hoists every catalog to the shared root, which is what a *branch*
|
|
17
|
+
* needs: each host looks for its catalog at the repository root and nowhere
|
|
18
|
+
* else. The three hosts that declare one look in three different places
|
|
19
|
+
* (`.claude-plugin/`, `.cursor-plugin/`, `.agents/plugins/`), so they coexist
|
|
20
|
+
* there without collision, and one branch serves all of them.
|
|
21
|
+
*/
|
|
22
|
+
export function catalogPathFor(layout, target, location) {
|
|
23
|
+
return layout === "release"
|
|
24
|
+
? `${location.directory}/${location.file}`
|
|
25
|
+
: `${target}/${location.directory}/${location.file}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `source` a catalog entry carries, relative to the catalog itself.
|
|
29
|
+
*
|
|
30
|
+
* Never rewritten to `./`, which is only correct when a catalog shares a
|
|
31
|
+
* directory with the single plugin it describes.
|
|
32
|
+
*/
|
|
33
|
+
export function sourceFor(layout, target, bundleName) {
|
|
34
|
+
return layout === "release" ? `./${target}/${bundleName}` : `./${bundleName}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* What the writer owns in the output directory: directories it may clear
|
|
38
|
+
* wholesale, and files it owns individually.
|
|
39
|
+
*
|
|
40
|
+
* This is the one computation that must not be approximated. A root the writer
|
|
41
|
+
* does not know it owns keeps stale files across a release — a bundle dropped
|
|
42
|
+
* upstream would go on being published indefinitely.
|
|
43
|
+
*/
|
|
44
|
+
export function ownership(layout, targets, paths) {
|
|
45
|
+
if (layout === "nested")
|
|
46
|
+
return {
|
|
47
|
+
managedRoots: [...targets],
|
|
48
|
+
looseFiles: paths.filter((item) => !targets.some((target) => item.startsWith(`${target}/`))),
|
|
49
|
+
};
|
|
50
|
+
// Release: every top-level directory this build produced is ours — the target
|
|
51
|
+
// trees, `bundles/`, each host's catalog directory, and any resource root
|
|
52
|
+
// hoisted alongside the sources. Derived from the artifacts rather than
|
|
53
|
+
// listed, because the resource roots are a property of the bundles and cannot
|
|
54
|
+
// be known here.
|
|
55
|
+
const roots = new Set();
|
|
56
|
+
const loose = [];
|
|
57
|
+
for (const item of paths) {
|
|
58
|
+
const slash = item.indexOf("/");
|
|
59
|
+
if (slash === -1)
|
|
60
|
+
loose.push(item);
|
|
61
|
+
else
|
|
62
|
+
roots.add(item.slice(0, slash));
|
|
63
|
+
}
|
|
64
|
+
// Byte comparison, never localeCompare: the same rule the rest of this module
|
|
65
|
+
// follows, so a differently configured runner cannot reorder the result.
|
|
66
|
+
return {
|
|
67
|
+
managedRoots: [...roots].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
68
|
+
looseFiles: loose,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/agent/marketplace/layout.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAU,CAAC;AASjE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAwB,EACxB,MAAmB,EACnB,QAAyB;IAEzB,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,GAAG,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE;QAC1C,CAAC,CAAC,GAAG,MAAM,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,MAAwB,EACxB,MAAmB,EACnB,UAAkB;IAElB,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;AAChF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,MAAwB,EACxB,OAAsB,EACtB,KAAe;IAEf,IAAI,MAAM,KAAK,QAAQ;QACrB,OAAO;YACL,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC;YAC1B,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;SAC7F,CAAC;IAEJ,8EAA8E;IAC9E,0EAA0E;IAC1E,wEAAwE;IACxE,8EAA8E;IAC9E,iBAAiB;IACjB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YAC9B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,8EAA8E;IAC9E,yEAAyE;IACzE,OAAO;QACL,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,UAAU,EAAE,KAAK;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Artifact } from "../types.js";
|
|
2
|
+
import type { CollectionTarget } from "./index.js";
|
|
3
|
+
import type { PublishedBundle } from "./source-bundles.js";
|
|
4
|
+
/** The manifest a release tree publishes at its root. */
|
|
5
|
+
export declare const RELEASE_MANIFEST = "release-manifest.json";
|
|
6
|
+
/**
|
|
7
|
+
* Hand-owned, and versions the document this file writes.
|
|
8
|
+
*
|
|
9
|
+
* Unrelated to the package version, to the bundle `schemaVersion`, to the
|
|
10
|
+
* collection spec's, or to any other version in this project.
|
|
11
|
+
*/
|
|
12
|
+
export declare const RELEASE_MANIFEST_SCHEMA = "1";
|
|
13
|
+
/**
|
|
14
|
+
* How a host is activated once a plugin is installed, flattened to a string a
|
|
15
|
+
* consumer can branch on without knowing cairn's internal profile shapes.
|
|
16
|
+
*
|
|
17
|
+
* This is not derivable from whether a target has a catalog: Cursor publishes a
|
|
18
|
+
* catalog and needs no activation at all, because it auto-scans its plugin
|
|
19
|
+
* directory. A consumer that assumed otherwise would pass `--register` where it
|
|
20
|
+
* does nothing and skip it where it is required.
|
|
21
|
+
*/
|
|
22
|
+
export type ReleaseActivation = "settings" | `cli:${string}` | null;
|
|
23
|
+
export interface ReleaseTargetEntry {
|
|
24
|
+
/** Collection-relative path of this host's catalog, or null when it has none. */
|
|
25
|
+
catalog: string | null;
|
|
26
|
+
/** Directory holding this host's rendered trees, or null when it has none. */
|
|
27
|
+
root: string | null;
|
|
28
|
+
activation: ReleaseActivation;
|
|
29
|
+
}
|
|
30
|
+
export interface ReleaseBundleTarget {
|
|
31
|
+
path: string;
|
|
32
|
+
sha256: string;
|
|
33
|
+
}
|
|
34
|
+
export interface ReleaseBundleEntry {
|
|
35
|
+
name: string;
|
|
36
|
+
version: string;
|
|
37
|
+
description: string;
|
|
38
|
+
/** Collection-relative path of the published source bundle. */
|
|
39
|
+
source: string;
|
|
40
|
+
/** Digest of that source tree — the thing a from-source install actually reads. */
|
|
41
|
+
sourceSha256: string;
|
|
42
|
+
targets: Record<string, ReleaseBundleTarget>;
|
|
43
|
+
}
|
|
44
|
+
export interface ReleaseManifest {
|
|
45
|
+
schemaVersion: string;
|
|
46
|
+
marketplace: string;
|
|
47
|
+
version: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
sourceCommit: string | null;
|
|
50
|
+
generator: {
|
|
51
|
+
name: string;
|
|
52
|
+
version: string;
|
|
53
|
+
};
|
|
54
|
+
targets: Record<string, ReleaseTargetEntry>;
|
|
55
|
+
bundles: ReleaseBundleEntry[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* sha256 over a subtree, covering path, executability and content.
|
|
59
|
+
*
|
|
60
|
+
* Byte-sorted POSIX paths, never `localeCompare` and never platform separators:
|
|
61
|
+
* a digest that depended on the runner's locale or operating system would
|
|
62
|
+
* differ between two builds of the same tree.
|
|
63
|
+
*/
|
|
64
|
+
export declare function treeDigest(artifacts: Artifact[], prefix: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* The release manifest: everything a consumer needs to install this branch
|
|
67
|
+
* without knowing anything about the repository that produced it.
|
|
68
|
+
*
|
|
69
|
+
* The document-level `targets` map is what lets one branch serve hosts that
|
|
70
|
+
* have no marketplace concept at all. A target with `catalog: null` is not
|
|
71
|
+
* absent from the release — it is installed from `source` instead, which is the
|
|
72
|
+
* whole reason the source bundles are published.
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildReleaseManifest(input: {
|
|
75
|
+
marketplace: string;
|
|
76
|
+
version: string;
|
|
77
|
+
description?: string;
|
|
78
|
+
sourceCommit?: string;
|
|
79
|
+
generator: {
|
|
80
|
+
name: string;
|
|
81
|
+
version: string;
|
|
82
|
+
};
|
|
83
|
+
targets: CollectionTarget[];
|
|
84
|
+
sources: PublishedBundle[];
|
|
85
|
+
descriptions: Map<string, string>;
|
|
86
|
+
artifacts: Artifact[];
|
|
87
|
+
}): Artifact;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { profileFor } from "../targets/index.js";
|
|
3
|
+
/** The manifest a release tree publishes at its root. */
|
|
4
|
+
export const RELEASE_MANIFEST = "release-manifest.json";
|
|
5
|
+
/**
|
|
6
|
+
* Hand-owned, and versions the document this file writes.
|
|
7
|
+
*
|
|
8
|
+
* Unrelated to the package version, to the bundle `schemaVersion`, to the
|
|
9
|
+
* collection spec's, or to any other version in this project.
|
|
10
|
+
*/
|
|
11
|
+
export const RELEASE_MANIFEST_SCHEMA = "1";
|
|
12
|
+
/**
|
|
13
|
+
* sha256 over a subtree, covering path, executability and content.
|
|
14
|
+
*
|
|
15
|
+
* Byte-sorted POSIX paths, never `localeCompare` and never platform separators:
|
|
16
|
+
* a digest that depended on the runner's locale or operating system would
|
|
17
|
+
* differ between two builds of the same tree.
|
|
18
|
+
*/
|
|
19
|
+
export function treeDigest(artifacts, prefix) {
|
|
20
|
+
const scoped = artifacts
|
|
21
|
+
.filter((artifact) => artifact.path === prefix || artifact.path.startsWith(`${prefix}/`))
|
|
22
|
+
.map((artifact) => ({ ...artifact, path: artifact.path.slice(prefix.length + 1) }))
|
|
23
|
+
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
24
|
+
const hash = createHash("sha256");
|
|
25
|
+
for (const artifact of scoped) {
|
|
26
|
+
hash.update(`${artifact.path}\0${artifact.mode & 0o111 ? "x" : "-"}\0`);
|
|
27
|
+
hash.update(artifact.content);
|
|
28
|
+
}
|
|
29
|
+
return hash.digest("hex");
|
|
30
|
+
}
|
|
31
|
+
function activationFor(target) {
|
|
32
|
+
const activation = profileFor(target).install?.user?.activation;
|
|
33
|
+
if (!activation)
|
|
34
|
+
return null;
|
|
35
|
+
return activation.form === "codex-plugin-cli" ? `cli:${activation.command}` : "settings";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The release manifest: everything a consumer needs to install this branch
|
|
39
|
+
* without knowing anything about the repository that produced it.
|
|
40
|
+
*
|
|
41
|
+
* The document-level `targets` map is what lets one branch serve hosts that
|
|
42
|
+
* have no marketplace concept at all. A target with `catalog: null` is not
|
|
43
|
+
* absent from the release — it is installed from `source` instead, which is the
|
|
44
|
+
* whole reason the source bundles are published.
|
|
45
|
+
*/
|
|
46
|
+
export function buildReleaseManifest(input) {
|
|
47
|
+
const targets = {};
|
|
48
|
+
for (const entry of input.targets)
|
|
49
|
+
targets[entry.target] = {
|
|
50
|
+
catalog: entry.catalog,
|
|
51
|
+
// The rendered tree, which exists whether or not the host has a catalog:
|
|
52
|
+
// antigravity gets a payload and no marketplace.
|
|
53
|
+
root: entry.plugins.length > 0 ? entry.target : null,
|
|
54
|
+
activation: activationFor(entry.target),
|
|
55
|
+
};
|
|
56
|
+
const bundles = input.sources.map((source) => {
|
|
57
|
+
const perTarget = {};
|
|
58
|
+
for (const entry of input.targets)
|
|
59
|
+
if (entry.plugins.some((plugin) => plugin.name === source.name)) {
|
|
60
|
+
const prefix = `${entry.target}/${source.name}`;
|
|
61
|
+
perTarget[entry.target] = { path: prefix, sha256: treeDigest(input.artifacts, prefix) };
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
name: source.name,
|
|
65
|
+
version: source.version,
|
|
66
|
+
description: input.descriptions.get(source.name) ?? "",
|
|
67
|
+
source: source.source,
|
|
68
|
+
sourceSha256: treeDigest(input.artifacts, source.source),
|
|
69
|
+
targets: perTarget,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
const manifest = {
|
|
73
|
+
schemaVersion: RELEASE_MANIFEST_SCHEMA,
|
|
74
|
+
marketplace: input.marketplace,
|
|
75
|
+
version: input.version,
|
|
76
|
+
...(input.description !== undefined ? { description: input.description } : {}),
|
|
77
|
+
sourceCommit: input.sourceCommit ?? null,
|
|
78
|
+
generator: input.generator,
|
|
79
|
+
targets,
|
|
80
|
+
bundles,
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
path: RELEASE_MANIFEST,
|
|
84
|
+
content: Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`),
|
|
85
|
+
mode: 0o644,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=release-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-manifest.js","sourceRoot":"","sources":["../../../src/agent/marketplace/release-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAIjD,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAgD3C;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,SAAqB,EAAE,MAAc;IAC9D,MAAM,MAAM,GAAG,SAAS;SACrB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;SACxF,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;SAClF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpE,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,aAAa,CAAC,MAAmB;IACxC,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC;IAChE,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,UAAU,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC,CAAC,OAAO,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;AAC3F,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAUpC;IACC,MAAM,OAAO,GAAuC,EAAE,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO;QAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,yEAAyE;YACzE,iDAAiD;YACjD,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;YACpD,UAAU,EAAE,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;SACxC,CAAC;IAEJ,MAAM,OAAO,GAAyB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACjE,MAAM,SAAS,GAAwC,EAAE,CAAC;QAC1D,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO;YAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChE,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAChD,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;YAC1F,CAAC;QACH,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;YACtD,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,YAAY,EAAE,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC;YACxD,OAAO,EAAE,SAAS;SACnB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAoB;QAChC,aAAa,EAAE,uBAAuB;QACtC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;QACxC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO;QACP,OAAO;KACR,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;QAC9D,IAAI,EAAE,KAAK;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Artifact } from "../types.js";
|
|
2
|
+
import type { ReleaseManifest } from "./release-manifest.js";
|
|
3
|
+
/**
|
|
4
|
+
* The landing page of a published release branch.
|
|
5
|
+
*
|
|
6
|
+
* Generated here rather than by each publishing repository, because otherwise
|
|
7
|
+
* every repository that publishes a release branch writes the same document
|
|
8
|
+
* generator — which is the duplication this layout exists to remove. The one
|
|
9
|
+
* thing cairn cannot know is which repository it is being published from, so
|
|
10
|
+
* that is the single input.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildReleaseReadme(manifest: ReleaseManifest, repository: string): Artifact;
|