opencode-ship 0.2.1 → 0.3.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/CHANGELOG.md +51 -16
- package/README.md +26 -12
- package/THIRD_PARTY_NOTICES.md +10 -0
- package/dist/cli.js +862 -453
- package/dist/core.js +1 -1
- package/dist/plugin.js +83 -9
- package/docs/adr/0001-opencode-ship-redesign.md +1 -1
- package/package.json +6 -1
- package/schema/project-adapter.schema.json +1 -1
- package/schema/ship-config.schema.json +1 -1
- package/schema/ship-lock.schema.json +1 -1
package/dist/core.js
CHANGED
package/dist/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// opencode-ship v0.
|
|
1
|
+
// opencode-ship v0.3.0
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __esm = (fn, res) => function __init() {
|
|
@@ -46,14 +46,20 @@ __export(lock_exports, {
|
|
|
46
46
|
CURRENT_LOCK_SCHEMA: () => CURRENT_LOCK_SCHEMA,
|
|
47
47
|
computeIntegrity: () => computeIntegrity,
|
|
48
48
|
lockPath: () => lockPath,
|
|
49
|
+
lockSchemaRevision: () => lockSchemaRevision,
|
|
49
50
|
migrateLegacyLock: () => migrateLegacyLock,
|
|
50
51
|
readLock: () => readLock2,
|
|
52
|
+
readValidatedLock: () => readValidatedLock,
|
|
51
53
|
validateIntegrity: () => validateIntegrity,
|
|
54
|
+
validateLock: () => validateLock,
|
|
52
55
|
writeLock: () => writeLock
|
|
53
56
|
});
|
|
54
57
|
import { readFile as readFile4, writeFile as writeFile4, rename as rename4, mkdir as mkdir4 } from "node:fs/promises";
|
|
55
58
|
import { existsSync as existsSync4 } from "node:fs";
|
|
56
59
|
import { dirname as dirname4, resolve as resolve8 } from "node:path";
|
|
60
|
+
function lockSchemaRevision() {
|
|
61
|
+
return CURRENT_LOCK_SCHEMA;
|
|
62
|
+
}
|
|
57
63
|
function lockPath(repoRoot) {
|
|
58
64
|
return resolve8(repoRoot, ".opencode", "ship.lock.json");
|
|
59
65
|
}
|
|
@@ -91,6 +97,68 @@ async function validateIntegrity(lock) {
|
|
|
91
97
|
const expected = computeIntegrity(lock).lockSha256;
|
|
92
98
|
return expected === lock.integrity.lockSha256;
|
|
93
99
|
}
|
|
100
|
+
function validateLock(rawLock) {
|
|
101
|
+
if (rawLock === null || rawLock === void 0) {
|
|
102
|
+
return { ok: true, kind: "missing", issues: [] };
|
|
103
|
+
}
|
|
104
|
+
if (typeof rawLock !== "object" || Array.isArray(rawLock)) {
|
|
105
|
+
return { ok: false, kind: "shape", issues: ["lock root must be an object"] };
|
|
106
|
+
}
|
|
107
|
+
const issues = [];
|
|
108
|
+
let kind = "ok";
|
|
109
|
+
if (rawLock.contractVersion !== CURRENT_LOCK_SCHEMA) {
|
|
110
|
+
issues.push(`unsupported contractVersion: ${JSON.stringify(rawLock.contractVersion)} (expected ${CURRENT_LOCK_SCHEMA})`);
|
|
111
|
+
kind = "schema";
|
|
112
|
+
}
|
|
113
|
+
const manager = rawLock.manager;
|
|
114
|
+
if (manager === void 0) {
|
|
115
|
+
issues.push("manager section missing");
|
|
116
|
+
kind = kind === "ok" ? "shape" : kind;
|
|
117
|
+
} else if (typeof manager !== "object" || manager === null) {
|
|
118
|
+
issues.push("manager section must be an object");
|
|
119
|
+
kind = kind === "ok" ? "shape" : kind;
|
|
120
|
+
} else if (manager.schemaVersion !== CURRENT_LOCK_SCHEMA) {
|
|
121
|
+
issues.push(`unsupported manager.schemaVersion: ${JSON.stringify(manager.schemaVersion)} (expected ${CURRENT_LOCK_SCHEMA})`);
|
|
122
|
+
kind = "schema";
|
|
123
|
+
} else if (manager.name !== "opencode-ship") {
|
|
124
|
+
issues.push(`unknown manager.name: ${JSON.stringify(manager.name)}`);
|
|
125
|
+
kind = "shape";
|
|
126
|
+
}
|
|
127
|
+
if (!rawLock.files || !Array.isArray(rawLock.files)) {
|
|
128
|
+
issues.push("files must be an array");
|
|
129
|
+
kind = kind === "ok" ? "shape" : kind;
|
|
130
|
+
}
|
|
131
|
+
if (!rawLock.integrity || typeof rawLock.integrity !== "object") {
|
|
132
|
+
issues.push("integrity section missing");
|
|
133
|
+
kind = kind === "ok" ? "shape" : kind;
|
|
134
|
+
} else {
|
|
135
|
+
const expected = computeIntegrity(rawLock).lockSha256;
|
|
136
|
+
if (expected !== rawLock.integrity.lockSha256) {
|
|
137
|
+
issues.push(`integrity mismatch: stored ${rawLock.integrity.lockSha256} != computed ${expected}`);
|
|
138
|
+
kind = "integrity";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { ok: issues.length === 0, kind, issues };
|
|
142
|
+
}
|
|
143
|
+
async function readValidatedLock(repoRoot) {
|
|
144
|
+
const path = lockPath(repoRoot);
|
|
145
|
+
if (!existsSync4(path)) {
|
|
146
|
+
return { kind: "missing", lock: null, issues: [] };
|
|
147
|
+
}
|
|
148
|
+
let raw;
|
|
149
|
+
try {
|
|
150
|
+
const text = await readFile4(path, "utf8");
|
|
151
|
+
raw = JSON.parse(text);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return {
|
|
154
|
+
kind: "integrity",
|
|
155
|
+
lock: null,
|
|
156
|
+
issues: [`unable to parse lock JSON: ${e?.message ?? String(e)}`]
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const validation = validateLock(raw);
|
|
160
|
+
return { kind: validation.kind, lock: validation.ok ? raw : null, issues: validation.issues };
|
|
161
|
+
}
|
|
94
162
|
async function migrateLegacyLock(repoRoot) {
|
|
95
163
|
const legacy = resolve8(repoRoot, ".opencode", "delivery.lock.json");
|
|
96
164
|
if (!existsSync4(legacy)) return null;
|
|
@@ -12540,7 +12608,7 @@ function tool(input) {
|
|
|
12540
12608
|
tool.schema = external_exports;
|
|
12541
12609
|
|
|
12542
12610
|
// src/plugin.js
|
|
12543
|
-
import { resolve as
|
|
12611
|
+
import { resolve as resolve12 } from "node:path";
|
|
12544
12612
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
12545
12613
|
|
|
12546
12614
|
// src/adapter.js
|
|
@@ -12765,7 +12833,7 @@ function parseRepoSlug(slug) {
|
|
|
12765
12833
|
|
|
12766
12834
|
// src/drivers/gh-cli.js
|
|
12767
12835
|
function defaultRunner(cwd, env) {
|
|
12768
|
-
return (args) => new Promise((
|
|
12836
|
+
return (args) => new Promise((resolve13, reject2) => {
|
|
12769
12837
|
const proc = spawn("gh", args, {
|
|
12770
12838
|
cwd,
|
|
12771
12839
|
env,
|
|
@@ -12777,7 +12845,7 @@ function defaultRunner(cwd, env) {
|
|
|
12777
12845
|
proc.stdout.on("data", (d) => stdout += d.toString());
|
|
12778
12846
|
proc.stderr.on("data", (d) => stderr += d.toString());
|
|
12779
12847
|
proc.on("error", reject2);
|
|
12780
|
-
proc.on("close", (status) =>
|
|
12848
|
+
proc.on("close", (status) => resolve13({ status: status ?? -1, stdout, stderr }));
|
|
12781
12849
|
});
|
|
12782
12850
|
}
|
|
12783
12851
|
function viewFields() {
|
|
@@ -14207,7 +14275,7 @@ import { dirname as dirname3, resolve as resolve7 } from "node:path";
|
|
|
14207
14275
|
// schema/ship-config.schema.json
|
|
14208
14276
|
var ship_config_schema_default = {
|
|
14209
14277
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
14210
|
-
$id: "https://github.com/Viktorxyz/opencode-
|
|
14278
|
+
$id: "https://github.com/Viktorxyz/opencode-ship/schema/ship-config.schema.json",
|
|
14211
14279
|
title: "opencode-ship user config",
|
|
14212
14280
|
type: "object",
|
|
14213
14281
|
required: ["schemaVersion"],
|
|
@@ -14805,8 +14873,14 @@ function flattenShipConfig(ship) {
|
|
|
14805
14873
|
return adapter;
|
|
14806
14874
|
}
|
|
14807
14875
|
|
|
14876
|
+
// src/version.js
|
|
14877
|
+
import { readFileSync as readFileSync2, existsSync as existsSync6 } from "node:fs";
|
|
14878
|
+
import { dirname as dirname5, resolve as resolve11 } from "node:path";
|
|
14879
|
+
import { fileURLToPath } from "node:url";
|
|
14880
|
+
var PACKAGE_VERSION = "0.3.0";
|
|
14881
|
+
var TEMPLATE_SET = `v${PACKAGE_VERSION}`;
|
|
14882
|
+
|
|
14808
14883
|
// src/plugin.js
|
|
14809
|
-
var VERSION = "0.2.1";
|
|
14810
14884
|
var toolDefs = [
|
|
14811
14885
|
["delivery_inspect", "Inspect a manifest and a project-local doctor report.", "inspect"],
|
|
14812
14886
|
["delivery_issue", "Find or create the issue for a delivery task.", "issue"],
|
|
@@ -14843,7 +14917,7 @@ async function resolveRepoSlug(repoRoot, detection, config2) {
|
|
|
14843
14917
|
const fromConfig = config2?.value?.project?.repository;
|
|
14844
14918
|
if (typeof fromConfig === "string" && fromConfig.includes("/")) return fromConfig;
|
|
14845
14919
|
if (detection?.repository) return detection.repository;
|
|
14846
|
-
const gitConfig = await readFile5(
|
|
14920
|
+
const gitConfig = await readFile5(resolve12(repoRoot, ".git/config"), "utf8").catch(() => null);
|
|
14847
14921
|
if (gitConfig) {
|
|
14848
14922
|
const m = gitConfig.match(/url\s*=\s*.*?github\.com[:/]([^/]+)\/([^/\s]+?)(?:\.git)?\b/);
|
|
14849
14923
|
if (m) return `${m[1]}/${m[2]}`;
|
|
@@ -14875,7 +14949,7 @@ async function bestEffortCleanupQueue(repoRoot, adapter) {
|
|
|
14875
14949
|
return { pending, manifestTasks: tasks.map((t) => t.taskId), ...out };
|
|
14876
14950
|
}
|
|
14877
14951
|
async function buildRuntime(worktree) {
|
|
14878
|
-
const repoRootAbs =
|
|
14952
|
+
const repoRootAbs = resolve12(worktree ?? process.cwd());
|
|
14879
14953
|
const detection = detectProject(repoRootAbs);
|
|
14880
14954
|
const legacyAdapter = await loadAdapter(repoRootAbs);
|
|
14881
14955
|
const config2 = await loadConfig(repoRootAbs);
|
|
@@ -14898,7 +14972,7 @@ async function buildRuntime(worktree) {
|
|
|
14898
14972
|
repoSlug: repoSlug ?? "owner/repo",
|
|
14899
14973
|
owner,
|
|
14900
14974
|
driver,
|
|
14901
|
-
packageVersion:
|
|
14975
|
+
packageVersion: PACKAGE_VERSION,
|
|
14902
14976
|
lastTaskId: null,
|
|
14903
14977
|
cleanupQueueOnStartup: cleanup,
|
|
14904
14978
|
recover: () => recoverManifestAfterCrash
|
|
@@ -40,7 +40,7 @@ with three surfaces:
|
|
|
40
40
|
|
|
41
41
|
Five output classes are installer-managed and recorded in the lock:
|
|
42
42
|
|
|
43
|
-
- `.opencode/
|
|
43
|
+
- `.opencode/plugins/opencode-ship.js` — the bundled plugin.
|
|
44
44
|
- `.opencode/agents/delivery-reviewer.md`,
|
|
45
45
|
`.opencode/agents/delivery-verifier.md`.
|
|
46
46
|
- `.opencode/skills/delivery-workflow/SKILL.md`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-ship",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "npm-distributed OpenCode installer that materializes the delivery plugin, reviewer/verifier agents, skills, ship config and lock into any consumer repository.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"node": ">=22.6.0",
|
|
18
18
|
"opencode": ">=1.15.5"
|
|
19
19
|
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"provenance": true
|
|
23
|
+
},
|
|
20
24
|
"peerDependencies": {
|
|
21
25
|
"@opencode-ai/plugin": ">=1.15.5 <2"
|
|
22
26
|
},
|
|
@@ -43,6 +47,7 @@
|
|
|
43
47
|
"assets",
|
|
44
48
|
"schema",
|
|
45
49
|
"docs",
|
|
50
|
+
"THIRD_PARTY_NOTICES.md",
|
|
46
51
|
"README.md",
|
|
47
52
|
"CHANGELOG.md",
|
|
48
53
|
"LICENSE"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://github.com/Viktorxyz/opencode-
|
|
3
|
+
"$id": "https://github.com/Viktorxyz/opencode-ship/schema/project-adapter.schema.json",
|
|
4
4
|
"title": "opencode-ship project adapter",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["contractVersion"],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://github.com/Viktorxyz/opencode-
|
|
3
|
+
"$id": "https://github.com/Viktorxyz/opencode-ship/schema/ship-config.schema.json",
|
|
4
4
|
"title": "opencode-ship user config",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["schemaVersion"],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://github.com/Viktorxyz/opencode-
|
|
3
|
+
"$id": "https://github.com/Viktorxyz/opencode-ship/schema/ship-lock.schema.json",
|
|
4
4
|
"title": "opencode-ship install lock",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["contractVersion", "manager", "files", "integrity"],
|