@code-partner/codepipe-hub 0.14.1-dev.389.g16ca7a21 → 0.14.1-dev.392.g2ee041d5
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/admin/dist/assets/{index-C4jvxAyb.js → index-C1be47HC.js} +5 -5
- package/admin/dist/index.html +1 -1
- package/dashboard/dist/assets/{ModelCanvas-CPPfRBQg.js → ModelCanvas-B2M4zQnV.js} +1 -1
- package/dashboard/dist/assets/{index-Bgq2ZBdp.js → index-Cpy8aKZb.js} +116 -116
- package/dashboard/dist/index.html +1 -1
- package/hub/dist/index.js +96 -29
- package/package.json +1 -1
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
localStorage.getItem('theme') ?? 'dark'
|
|
28
28
|
);
|
|
29
29
|
</script>
|
|
30
|
-
<script type="module" crossorigin src="/assets/index-
|
|
30
|
+
<script type="module" crossorigin src="/assets/index-Cpy8aKZb.js"></script>
|
|
31
31
|
<link rel="stylesheet" crossorigin href="/assets/index-CD8JrtmW.css">
|
|
32
32
|
</head>
|
|
33
33
|
<body>
|
package/hub/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var PLATFORM_VERSION;
|
|
|
13
13
|
var init_version_generated = __esm({
|
|
14
14
|
"../packages/shared/dist/version.generated.js"() {
|
|
15
15
|
"use strict";
|
|
16
|
-
PLATFORM_VERSION = "0.14.1-dev.
|
|
16
|
+
PLATFORM_VERSION = "0.14.1-dev.392.g2ee041d5";
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
19
|
|
|
@@ -41,6 +41,15 @@ var init_hub_url = __esm({
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
// ../packages/shared/dist/local-hub.js
|
|
45
|
+
var LOCAL_HUB_OWNER_EMAIL;
|
|
46
|
+
var init_local_hub = __esm({
|
|
47
|
+
"../packages/shared/dist/local-hub.js"() {
|
|
48
|
+
"use strict";
|
|
49
|
+
LOCAL_HUB_OWNER_EMAIL = "local-owner@localhost";
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
44
53
|
// ../packages/shared/dist/context-template.js
|
|
45
54
|
var init_context_template = __esm({
|
|
46
55
|
"../packages/shared/dist/context-template.js"() {
|
|
@@ -1287,20 +1296,24 @@ var init_project_settings = __esm({
|
|
|
1287
1296
|
{
|
|
1288
1297
|
id: "llm",
|
|
1289
1298
|
label: "LLM",
|
|
1290
|
-
// DEV-510 (ADR-0025): the project's LLM provider
|
|
1291
|
-
//
|
|
1292
|
-
//
|
|
1299
|
+
// DEV-510 (ADR-0025): the project's LLM provider. DEV-760 made the second
|
|
1300
|
+
// harness real, so this is a genuine choice — the enum carries every
|
|
1301
|
+
// provider the runtime supports. Rendered above the per-role model
|
|
1302
|
+
// sub-group.
|
|
1293
1303
|
fields: [
|
|
1294
1304
|
{
|
|
1295
1305
|
id: "llm.provider",
|
|
1296
1306
|
file: "local.yaml",
|
|
1297
1307
|
path: ["llm", "provider"],
|
|
1298
1308
|
type: "enum",
|
|
1299
|
-
label: "
|
|
1300
|
-
// Always a concrete provider
|
|
1309
|
+
label: "Default provider",
|
|
1310
|
+
// Always a concrete provider — never cleared.
|
|
1301
1311
|
nullable: false,
|
|
1302
1312
|
suggestions: [...LLM_PROVIDER_SUGGESTIONS],
|
|
1303
|
-
|
|
1313
|
+
// DEV-896: the old text ("currently only claude is available") outlived
|
|
1314
|
+
// its truth and read as "there is nothing to choose" — the one thing
|
|
1315
|
+
// help must never say about a live control.
|
|
1316
|
+
help: "The agent harness every role runs on by default. Per-role overrides (and the fallback agent) live in the shared config's routing block."
|
|
1304
1317
|
}
|
|
1305
1318
|
],
|
|
1306
1319
|
groups: [
|
|
@@ -2301,6 +2314,13 @@ var init_runner = __esm({
|
|
|
2301
2314
|
}
|
|
2302
2315
|
});
|
|
2303
2316
|
|
|
2317
|
+
// ../packages/shared/dist/git-transport.js
|
|
2318
|
+
var init_git_transport = __esm({
|
|
2319
|
+
"../packages/shared/dist/git-transport.js"() {
|
|
2320
|
+
"use strict";
|
|
2321
|
+
}
|
|
2322
|
+
});
|
|
2323
|
+
|
|
2304
2324
|
// ../packages/shared/dist/delivery-config.js
|
|
2305
2325
|
function localFirstDefaults() {
|
|
2306
2326
|
return {
|
|
@@ -3001,6 +3021,7 @@ var init_dist = __esm({
|
|
|
3001
3021
|
"use strict";
|
|
3002
3022
|
init_version();
|
|
3003
3023
|
init_hub_url();
|
|
3024
|
+
init_local_hub();
|
|
3004
3025
|
init_context_template();
|
|
3005
3026
|
init_project_map();
|
|
3006
3027
|
init_phase();
|
|
@@ -3026,6 +3047,7 @@ var init_dist = __esm({
|
|
|
3026
3047
|
init_farm();
|
|
3027
3048
|
init_runner();
|
|
3028
3049
|
init_project();
|
|
3050
|
+
init_git_transport();
|
|
3029
3051
|
init_delivery_config();
|
|
3030
3052
|
init_delivery_capabilities();
|
|
3031
3053
|
init_revision_ref();
|
|
@@ -10488,10 +10510,26 @@ async function loadSourceSnapshots(db, projectId) {
|
|
|
10488
10510
|
async function dirtySourceRepos(db, projectId) {
|
|
10489
10511
|
return (await loadSourceSnapshots(db, projectId)).filter((s) => s.dirty).map((s) => s.repoName);
|
|
10490
10512
|
}
|
|
10513
|
+
async function unpinnedSourceRepos(db, projectId) {
|
|
10514
|
+
const axes = await loadDeliveryAxes(db, projectId, {
|
|
10515
|
+
localFirstDefault: deliveryProfileLocalFirst()
|
|
10516
|
+
});
|
|
10517
|
+
if (axes.source.kind !== "local_snapshot") return [];
|
|
10518
|
+
const row = await db.get(
|
|
10519
|
+
`SELECT repos_json as reposJson FROM projects WHERE id = ?`,
|
|
10520
|
+
projectId
|
|
10521
|
+
);
|
|
10522
|
+
if (!row) return [];
|
|
10523
|
+
const repos = JSON.parse(row.reposJson);
|
|
10524
|
+
const pinned = new Set((await loadSourceSnapshots(db, projectId)).map((s) => s.repoName));
|
|
10525
|
+
return repos.map((r) => r.name).filter((name) => !pinned.has(name));
|
|
10526
|
+
}
|
|
10491
10527
|
var SHA_RE;
|
|
10492
10528
|
var init_source_snapshots = __esm({
|
|
10493
10529
|
"src/projects/source-snapshots.ts"() {
|
|
10494
10530
|
"use strict";
|
|
10531
|
+
init_delivery_plan();
|
|
10532
|
+
init_publication();
|
|
10495
10533
|
SHA_RE = /^[0-9a-f]{40}$/;
|
|
10496
10534
|
}
|
|
10497
10535
|
});
|
|
@@ -10839,18 +10877,32 @@ async function claimNextJob(db, sandboxId, capabilities, lane) {
|
|
|
10839
10877
|
// produced a delivery whose diff carried the whole branch's work and could
|
|
10840
10878
|
// never cherry-pick back. The conflict source (the default branch) is now
|
|
10841
10879
|
// merged INTO the tip worktree by the SANDBOX (metadata.mergeBranchByRepo).
|
|
10880
|
+
// DEV-875: the SOURCE is re-resolved here too, for every role. A spec is
|
|
10881
|
+
// built when the job is queued, and a local-first project's pin may not
|
|
10882
|
+
// exist yet at that moment (the CLI reports it on start) — the spec then
|
|
10883
|
+
// froze the remote URL, which such a project may have no credential for.
|
|
10884
|
+
// Re-resolving at claim time hands the worker wherever the code actually
|
|
10885
|
+
// is now: the relay pin, or the mirror a project gained since.
|
|
10842
10886
|
rewriteSpec: async (tx, row) => {
|
|
10843
|
-
|
|
10844
|
-
return null;
|
|
10845
|
-
}
|
|
10887
|
+
const roleTakesChainRef = row.role === "implement" || row.role === "analyze" || row.role === "estimate" || row.role === "resolve-conflict";
|
|
10846
10888
|
const txDb = dbOf(tx);
|
|
10847
|
-
const
|
|
10848
|
-
const
|
|
10849
|
-
const defaultRefByRepo = new Map(
|
|
10850
|
-
(await loadProjectRepoRefs(txDb, row.projectId)).map((r) => [r.name, r.ref])
|
|
10851
|
-
);
|
|
10889
|
+
const current = await loadProjectRepoRefs(txDb, row.projectId);
|
|
10890
|
+
const currentByRepo = new Map(current.map((r) => [r.name, r]));
|
|
10852
10891
|
const spec2 = JSON.parse(row.specJson);
|
|
10892
|
+
if (spec2.metadata?.["externalReview"] === true) return null;
|
|
10853
10893
|
let changed = false;
|
|
10894
|
+
for (const repo of spec2.projectRepos) {
|
|
10895
|
+
const fresh = currentByRepo.get(repo.name);
|
|
10896
|
+
if (!fresh || fresh.cloneUrl === repo.cloneUrl) continue;
|
|
10897
|
+
repo.cloneUrl = fresh.cloneUrl;
|
|
10898
|
+
repo.ref = fresh.ref;
|
|
10899
|
+
if (fresh.defaultBranch) repo.defaultBranch = fresh.defaultBranch;
|
|
10900
|
+
changed = true;
|
|
10901
|
+
}
|
|
10902
|
+
if (!roleTakesChainRef) return changed ? JSON.stringify(spec2) : null;
|
|
10903
|
+
const chainRef = await loadChainTaskRef(txDb, row.taskId);
|
|
10904
|
+
const baseByRepo = chainRef ? await clusterBranchByRepo(txDb, chainRef) : {};
|
|
10905
|
+
const defaultRefByRepo = new Map(current.map((r) => [r.name, r.ref]));
|
|
10854
10906
|
for (const repo of spec2.projectRepos) {
|
|
10855
10907
|
const next = baseByRepo[repo.name] ?? defaultRefByRepo.get(repo.name) ?? repo.ref;
|
|
10856
10908
|
if (next !== repo.ref) {
|
|
@@ -18485,6 +18537,17 @@ async function developFromQueue(db, task, log, reason = "queue \u2192 develop")
|
|
|
18485
18537
|
async function startTaskWorkflow(db, task, log) {
|
|
18486
18538
|
await beginPipeline(db, task, log);
|
|
18487
18539
|
}
|
|
18540
|
+
async function localSourceHold(db, projectId) {
|
|
18541
|
+
const dirty = await dirtySourceRepos(db, projectId);
|
|
18542
|
+
if (dirty.length > 0) {
|
|
18543
|
+
return `LOCAL_SOURCE_DIRTY: uncommitted changes in ${dirty.join(", ")} \u2014 commit or stash them, then retry`;
|
|
18544
|
+
}
|
|
18545
|
+
const unpinned = await unpinnedSourceRepos(db, projectId);
|
|
18546
|
+
if (unpinned.length > 0) {
|
|
18547
|
+
return `LOCAL_SOURCE_UNPINNED: no snapshot of ${unpinned.join(", ")} yet \u2014 start this project's CLI (\`codepipe up\`) so it publishes your current commit, then retry`;
|
|
18548
|
+
}
|
|
18549
|
+
return null;
|
|
18550
|
+
}
|
|
18488
18551
|
async function beginPipeline(db, task, log) {
|
|
18489
18552
|
if (task.phase !== "INTAKE") return;
|
|
18490
18553
|
const deliveryPlan = await resolveProjectDeliveryPlan(db, task.projectId);
|
|
@@ -18494,11 +18557,10 @@ async function beginPipeline(db, task, log) {
|
|
|
18494
18557
|
return;
|
|
18495
18558
|
}
|
|
18496
18559
|
if (deliveryPlan.plan.transport === "context_repo" && deliveryPlan.plan.target === "working_repo") {
|
|
18497
|
-
const
|
|
18498
|
-
if (
|
|
18499
|
-
|
|
18500
|
-
|
|
18501
|
-
await transitionPhase(db, task.id, "NEEDS_MANUAL", reason);
|
|
18560
|
+
const hold = await localSourceHold(db, task.projectId);
|
|
18561
|
+
if (hold) {
|
|
18562
|
+
log.warn({ taskId: task.id, hold }, "local source not usable \u2014 execution held");
|
|
18563
|
+
await transitionPhase(db, task.id, "NEEDS_MANUAL", hold);
|
|
18502
18564
|
return;
|
|
18503
18565
|
}
|
|
18504
18566
|
}
|
|
@@ -19663,11 +19725,10 @@ async function triggerRework(db, task, instruction, source, log) {
|
|
|
19663
19725
|
return;
|
|
19664
19726
|
}
|
|
19665
19727
|
if (deliveryPlan.plan.target === "working_repo") {
|
|
19666
|
-
const
|
|
19667
|
-
if (
|
|
19668
|
-
|
|
19669
|
-
|
|
19670
|
-
await transitionPhase(db, task.id, "NEEDS_MANUAL", reason);
|
|
19728
|
+
const hold = await localSourceHold(db, task.projectId);
|
|
19729
|
+
if (hold) {
|
|
19730
|
+
log.warn({ taskId: task.id, hold }, "local source not usable \u2014 rework held");
|
|
19731
|
+
await transitionPhase(db, task.id, "NEEDS_MANUAL", hold);
|
|
19671
19732
|
return;
|
|
19672
19733
|
}
|
|
19673
19734
|
}
|
|
@@ -22178,6 +22239,7 @@ var init_ws = __esm({
|
|
|
22178
22239
|
init_dist();
|
|
22179
22240
|
|
|
22180
22241
|
// src/config.ts
|
|
22242
|
+
init_dist();
|
|
22181
22243
|
import { randomBytes } from "node:crypto";
|
|
22182
22244
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
22183
22245
|
import { resolve } from "node:path";
|
|
@@ -22305,8 +22367,8 @@ function loadLocalConfig() {
|
|
|
22305
22367
|
baseUrl: process.env["HUB_BASE_URL"] ?? `http://127.0.0.1:${port}`,
|
|
22306
22368
|
consoleBaseUrl: "",
|
|
22307
22369
|
databaseUrl: `sqlite:${resolve(dataDir, "codepipe.db")}`,
|
|
22308
|
-
adminEmail:
|
|
22309
|
-
registrationNotifyEmail:
|
|
22370
|
+
adminEmail: LOCAL_HUB_OWNER_EMAIL,
|
|
22371
|
+
registrationNotifyEmail: LOCAL_HUB_OWNER_EMAIL,
|
|
22310
22372
|
sessionCookieSecret: process.env["HUB_SESSION_COOKIE_SECRET"] ?? localSecret(dataDir, "session-secret", 32),
|
|
22311
22373
|
// The break-glass ownerless registration token must never be well-known:
|
|
22312
22374
|
// any process reaching the loopback port could otherwise register a
|
|
@@ -27208,10 +27270,12 @@ async function authRoutes(app, deps) {
|
|
|
27208
27270
|
const session = await readSession(db, req);
|
|
27209
27271
|
if (!session) return reply.status(401).send({ error: "no_session" });
|
|
27210
27272
|
const user = await findUser(db, session.email);
|
|
27273
|
+
const singleOwner = profileAxes(config.profile ?? "server").authProvider === "single-owner";
|
|
27211
27274
|
return {
|
|
27212
27275
|
email: session.email,
|
|
27213
27276
|
isSuperAdmin: isSuperUser(config, session.email),
|
|
27214
|
-
passwordSet: user === null || user.passwordHash !== null
|
|
27277
|
+
passwordSet: singleOwner || user === null || user.passwordHash !== null,
|
|
27278
|
+
singleOwner
|
|
27215
27279
|
};
|
|
27216
27280
|
});
|
|
27217
27281
|
app.post("/auth/logout", async (req, reply) => {
|
|
@@ -29626,7 +29690,10 @@ var createProjectBodySchema = {
|
|
|
29626
29690
|
type: "object",
|
|
29627
29691
|
required: ["host", "owner", "name", "cloneUrl", "branch"],
|
|
29628
29692
|
properties: {
|
|
29629
|
-
|
|
29693
|
+
// DEV-875: `local` = a bare repository on the CLI's machine, reported
|
|
29694
|
+
// with its filesystem path as `cloneUrl`. The HUB records it like any
|
|
29695
|
+
// other location — it has no git access to either kind.
|
|
29696
|
+
host: { type: "string", enum: ["github", "bitbucket", "gitlab", "local"] },
|
|
29630
29697
|
owner: { type: "string", minLength: 1 },
|
|
29631
29698
|
name: { type: "string", minLength: 1 },
|
|
29632
29699
|
cloneUrl: { type: "string", minLength: 1 },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-partner/codepipe-hub",
|
|
3
|
-
"version": "0.14.1-dev.
|
|
3
|
+
"version": "0.14.1-dev.392.g2ee041d5",
|
|
4
4
|
"description": "The CodePipe hub, packaged for one machine: the CLI installs it on demand for the local profile.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./hub/dist/index.js",
|