Merge current master and qualify managed Codex onboarding

Reconcile actual master 833769ab with preserved Codex 1a0ca662 and reviewed private onboarding preparation a758b226. Preserve the merged prerequisite and current native/security changes, saved runner choices, managed-image qualification and current Storybook identities.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-13 10:21:06 -05:00
commit 7956056b2f
951 files changed
+243773 -32509

No files matched your search

+119 -198
View File
@@ -62,6 +62,109 @@ function company(overrides: Record<string, unknown> = {}) {
};
}
function allImportEntities(): CompanyPortabilityPreviewResult["include"] {
return {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
};
}
function sourceCompanyManifest(): NonNullable<CompanyPortabilityPreviewResult["manifest"]["company"]> {
return {
path: "COMPANY.md",
name: "Source Co",
description: null,
logoPath: null,
requireBoardApprovalForNewAgents: false,
feedbackDataSharingEnabled: false,
feedbackDataSharingConsentAt: null,
feedbackDataSharingConsentByUserId: null,
feedbackDataSharingTermsVersion: null,
};
}
function ceoManifest(): CompanyPortabilityPreviewResult["manifest"]["agents"][number] {
return {
slug: "ceo",
name: "CEO",
path: "agents/ceo/AGENT.md",
skills: [],
role: "ceo",
title: null,
icon: null,
capabilities: null,
reportsToSlug: null,
reportsToExistingAgentId: null,
reportsToExistingAgentSlug: null,
adapterType: "codex_local",
adapterConfig: {},
runtimeConfig: {},
permissions: {},
permissionGrants: [],
budgetMonthlyCents: 0,
metadata: null,
};
}
function alphaProjectManifest(): CompanyPortabilityPreviewResult["manifest"]["projects"][number] {
return {
slug: "alpha",
name: "Alpha",
path: "projects/alpha/PROJECT.md",
description: null,
ownerAgentSlug: null,
leadAgentSlug: null,
targetDate: null,
color: null,
icon: null,
status: null,
executionWorkspacePolicy: null,
workspaces: [],
env: null,
metadata: null,
};
}
function kickoffIssueManifest(): CompanyPortabilityPreviewResult["manifest"]["issues"][number] {
return {
slug: "kickoff",
identifier: null,
title: "Kickoff",
path: "projects/alpha/issues/kickoff/TASK.md",
projectSlug: "alpha",
projectWorkspaceKey: null,
assigneeAgentSlug: "ceo",
description: null,
recurring: false,
routine: null,
legacyRecurrence: null,
status: null,
priority: null,
labelIds: [],
billingCode: null,
executionWorkspaceSettings: null,
assigneeAdapterOverrides: null,
comments: [],
metadata: null,
};
}
function openAiEnvInput(): CompanyPortabilityPreviewResult["envInputs"][number] {
return {
key: "OPENAI_API_KEY",
description: null,
agentSlug: "ceo",
projectSlug: null,
kind: "secret",
requirement: "required",
defaultValue: null,
portability: "portable",
};
}
describe("company CLI commands", () => {
let fetchMock: ReturnType<typeof vi.fn>;
let logSpy: ReturnType<typeof vi.spyOn>;
@@ -298,13 +401,7 @@ describe("buildCompanyDashboardUrl", () => {
describe("renderCompanyImportPreview", () => {
it("summarizes the preview with counts, selection info, and truncated examples", () => {
const preview: CompanyPortabilityPreviewResult = {
include: {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
},
include: allImportEntities(),
targetCompanyId: "company-123",
targetCompanyName: "Imported Co",
collisionStrategy: "rename",
@@ -334,49 +431,14 @@ describe("renderCompanyImportPreview", () => {
companyId: "company-src",
companyName: "Source Co",
},
includes: {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
},
company: {
path: "COMPANY.md",
name: "Source Co",
description: null,
logoPath: null,
requireBoardApprovalForNewAgents: false,
feedbackDataSharingEnabled: false,
feedbackDataSharingConsentAt: null,
feedbackDataSharingConsentByUserId: null,
feedbackDataSharingTermsVersion: null,
},
includes: allImportEntities(),
company: sourceCompanyManifest(),
sidebar: {
agents: ["ceo"],
projects: ["alpha"],
},
agents: [
{
slug: "ceo",
name: "CEO",
path: "agents/ceo/AGENT.md",
skills: [],
role: "ceo",
title: null,
icon: null,
capabilities: null,
reportsToSlug: null,
reportsToExistingAgentId: null,
reportsToExistingAgentSlug: null,
adapterType: "codex_local",
adapterConfig: {},
runtimeConfig: {},
permissions: {},
permissionGrants: [],
budgetMonthlyCents: 0,
metadata: null,
},
ceoManifest(),
],
skills: [
{
@@ -395,73 +457,20 @@ describe("renderCompanyImportPreview", () => {
},
],
projects: [
{
slug: "alpha",
name: "Alpha",
path: "projects/alpha/PROJECT.md",
description: null,
ownerAgentSlug: null,
leadAgentSlug: null,
targetDate: null,
color: null,
icon: null,
status: null,
executionWorkspacePolicy: null,
workspaces: [],
env: null,
metadata: null,
},
alphaProjectManifest(),
],
issues: [
{
slug: "kickoff",
identifier: null,
title: "Kickoff",
path: "projects/alpha/issues/kickoff/TASK.md",
projectSlug: "alpha",
projectWorkspaceKey: null,
assigneeAgentSlug: "ceo",
description: null,
recurring: false,
routine: null,
legacyRecurrence: null,
status: null,
priority: null,
labelIds: [],
billingCode: null,
executionWorkspaceSettings: null,
assigneeAdapterOverrides: null,
comments: [],
metadata: null,
},
kickoffIssueManifest(),
],
envInputs: [
{
key: "OPENAI_API_KEY",
description: null,
agentSlug: "ceo",
projectSlug: null,
kind: "secret",
requirement: "required",
defaultValue: null,
portability: "portable",
},
openAiEnvInput(),
],
},
files: {
"COMPANY.md": "# Source Co",
},
envInputs: [
{
key: "OPENAI_API_KEY",
description: null,
agentSlug: "ceo",
projectSlug: null,
kind: "secret",
requirement: "required",
defaultValue: null,
portability: "portable",
},
openAiEnvInput(),
],
warnings: ["One warning"],
errors: ["One error"],
@@ -545,13 +554,7 @@ describe("renderCompanyImportResult", () => {
describe("import selection catalog", () => {
it("defaults to everything and keeps project selection separate from task selection", () => {
const preview: CompanyPortabilityPreviewResult = {
include: {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
},
include: allImportEntities(),
targetCompanyId: "company-123",
targetCompanyName: "Imported Co",
collisionStrategy: "rename",
@@ -569,13 +572,7 @@ describe("import selection catalog", () => {
companyId: "company-src",
companyName: "Source Co",
},
includes: {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
},
includes: allImportEntities(),
company: {
path: "COMPANY.md",
name: "Source Co",
@@ -592,26 +589,7 @@ describe("import selection catalog", () => {
projects: ["alpha"],
},
agents: [
{
slug: "ceo",
name: "CEO",
path: "agents/ceo/AGENT.md",
skills: [],
role: "ceo",
title: null,
icon: null,
capabilities: null,
reportsToSlug: null,
reportsToExistingAgentId: null,
reportsToExistingAgentSlug: null,
adapterType: "codex_local",
adapterConfig: {},
runtimeConfig: {},
permissions: {},
permissionGrants: [],
budgetMonthlyCents: 0,
metadata: null,
},
ceoManifest(),
],
skills: [
{
@@ -630,45 +608,10 @@ describe("import selection catalog", () => {
},
],
projects: [
{
slug: "alpha",
name: "Alpha",
path: "projects/alpha/PROJECT.md",
description: null,
ownerAgentSlug: null,
leadAgentSlug: null,
targetDate: null,
color: null,
icon: null,
status: null,
executionWorkspacePolicy: null,
workspaces: [],
env: null,
metadata: null,
},
alphaProjectManifest(),
],
issues: [
{
slug: "kickoff",
identifier: null,
title: "Kickoff",
path: "projects/alpha/issues/kickoff/TASK.md",
projectSlug: "alpha",
projectWorkspaceKey: null,
assigneeAgentSlug: "ceo",
description: null,
recurring: false,
routine: null,
legacyRecurrence: null,
status: null,
priority: null,
labelIds: [],
billingCode: null,
executionWorkspaceSettings: null,
assigneeAdapterOverrides: null,
comments: [],
metadata: null,
},
kickoffIssueManifest(),
],
envInputs: [],
},
@@ -720,13 +663,7 @@ describe("import selection catalog", () => {
it("includes extension file even when all entities are deselected", () => {
const preview: CompanyPortabilityPreviewResult = {
include: {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
},
include: allImportEntities(),
targetCompanyId: "company-123",
targetCompanyName: "Imported Co",
collisionStrategy: "rename",
@@ -744,24 +681,8 @@ describe("import selection catalog", () => {
companyId: "company-src",
companyName: "Source Co",
},
includes: {
company: true,
agents: true,
projects: true,
issues: true,
skills: true,
},
company: {
path: "COMPANY.md",
name: "Source Co",
description: null,
logoPath: null,
requireBoardApprovalForNewAgents: false,
feedbackDataSharingEnabled: false,
feedbackDataSharingConsentAt: null,
feedbackDataSharingConsentByUserId: null,
feedbackDataSharingTermsVersion: null,
},
includes: allImportEntities(),
company: sourceCompanyManifest(),
sidebar: {
agents: [],
projects: [],
+76 -131
View File
@@ -285,9 +285,37 @@ function buildSourceConfig(): PaperclipConfig {
};
}
function writeSeedConfigFiles(
sourceConfigPath: string,
targetConfigPath: string,
targetRoot: string,
targetPaths: ReturnType<typeof resolveWorktreeLocalPaths>,
sourceConfig: PaperclipConfig,
targetConfig: PaperclipConfig,
): void {
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
}
function initializeTestRepo(repoRoot: string): void {
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.name", "Test User"], { cwd: repoRoot, stdio: "ignore" });
fs.writeFileSync(path.join(repoRoot, "README.md"), "# temp\n", "utf8");
execFileSync("git", ["add", "README.md"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["commit", "-m", "Initial commit"], { cwd: repoRoot, stdio: "ignore" });
}
describe("worktree helpers", () => {
it("uses the repo-local config for the current worktree", () => {
const targetRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-current-worktree-"));
const targetRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-current-worktree-"));
try {
const localConfig = path.join(targetRoot, ".paperclip", "config.json");
fs.mkdirSync(path.dirname(localConfig), { recursive: true });
@@ -307,7 +335,7 @@ describe("worktree helpers", () => {
});
it("uses the repository config from a nested working directory", () => {
const targetRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-current-worktree-nested-"));
const targetRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-current-worktree-nested-"));
try {
execFileSync("git", ["init", "-q"], { cwd: targetRoot });
const nestedDirectory = path.join(targetRoot, "packages", "example", "src");
@@ -517,7 +545,7 @@ describe("worktree helpers", () => {
});
it("requires the seed process to own the target embedded Postgres lifecycle", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-live-target-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-live-target-"));
try {
fs.writeFileSync(
path.join(tempRoot, "postmaster.pid"),
@@ -531,18 +559,6 @@ describe("worktree helpers", () => {
}
});
it("surfaces a credential-safe diagnostic when the target shuts down during restore", () => {
expect(formatWorktreeSeedFailureDiagnostic(
"restore",
new Error(
"Failed to restore seed.sql.gz: FATAL: the database system is shutting down; psql error: write EPIPE",
),
)).toBe(
"Target embedded PostgreSQL shut down during restore. Stop any competing worktree service and retry the seed.",
);
expect(formatWorktreeSeedFailureDiagnostic("migrations", new Error("secret connection failure")))
.toBe("Seed failed during migrations.");
});
it("surfaces the missing credential artifact for authenticated seed validation", () => {
expect(formatWorktreeSeedFailureDiagnostic(
@@ -610,7 +626,7 @@ describe("worktree helpers", () => {
itEmbeddedPostgres("recognizes positive legacy database schema evidence", async () => {
const tempDb = await startEmbeddedPostgresTestDatabase("paperclip-worktree-legacy-evidence-");
onTestFinished(() => tempDb.cleanup());
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-legacy-config-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-legacy-config-"));
try {
const configPath = path.join(tempRoot, "config.json");
const sourceConfig = buildSourceConfig();
@@ -644,7 +660,7 @@ describe("worktree helpers", () => {
});
it("ensure-seeded seeds once and fast-exits on the verified manifest", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-ensure-seeded-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-ensure-seeded-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "worktree");
@@ -661,15 +677,7 @@ describe("worktree helpers", () => {
serverPort: 3199,
databasePort: 54999,
});
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
writeSeedConfigFiles(sourceConfigPath, targetConfigPath, targetRoot, targetPaths, sourceConfig, targetConfig);
markWorktreeSeedPending({ configPath: targetConfigPath, sourceConfigPath });
const seedDatabase = vi.fn().mockResolvedValue({
@@ -715,7 +723,7 @@ describe("worktree helpers", () => {
});
it("treats an unregistered markerless config as a normal non-worktree boot", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-unregistered-markerless-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-unregistered-markerless-"));
try {
const configPath = path.join(tempRoot, "config.json");
fs.writeFileSync(configPath, `${JSON.stringify(buildSourceConfig())}\n`);
@@ -740,7 +748,7 @@ describe("worktree helpers", () => {
});
it("honors a legacy complete marker without resolving a seed source", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-complete-marker-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-complete-marker-"));
try {
const configPath = path.join(tempRoot, "config.json");
fs.writeFileSync(configPath, `${JSON.stringify(buildSourceConfig())}\n`);
@@ -763,7 +771,7 @@ describe("worktree helpers", () => {
});
it("seeds a configured worktree with no seed markers when no legacy database is present", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-unmarked-empty-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-unmarked-empty-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "worktree");
@@ -780,15 +788,7 @@ describe("worktree helpers", () => {
serverPort: 3194,
databasePort: 54994,
});
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
writeSeedConfigFiles(sourceConfigPath, targetConfigPath, targetRoot, targetPaths, sourceConfig, targetConfig);
const inspectLegacyDatabase = vi.fn().mockResolvedValue(null);
const seedDatabase = vi.fn().mockResolvedValue(mockVerifiedSeedResult());
@@ -810,7 +810,7 @@ describe("worktree helpers", () => {
});
it("adopts a markerless legacy worktree only after validating its database schema", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-unmarked-legacy-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-unmarked-legacy-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "worktree");
@@ -827,15 +827,7 @@ describe("worktree helpers", () => {
serverPort: 3193,
databasePort: 54993,
});
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
writeSeedConfigFiles(sourceConfigPath, targetConfigPath, targetRoot, targetPaths, sourceConfig, targetConfig);
const seedDatabase = vi.fn();
await expect(ensureWorktreeSeeded(
@@ -858,7 +850,7 @@ describe("worktree helpers", () => {
});
it("managed ensure-seeded derives a valid source from the registered base workspace", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-managed-seed-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-managed-seed-"));
try {
const baseRoot = path.join(tempRoot, "base");
const sourceConfigPath = path.join(baseRoot, ".paperclip", "config.json");
@@ -907,7 +899,7 @@ describe("worktree helpers", () => {
it.each(["sibling", "foreign_instance", "symlink", "instance_mismatch"] as const)(
"managed ensure-seeded re-derives a stale %s manifest source from registration",
async (variant) => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), `paperclip-worktree-managed-${variant}-`));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), `paperclip-worktree-managed-${variant}-`));
try {
const baseRoot = path.join(tempRoot, "base");
const canonicalSource = path.join(baseRoot, ".paperclip", "config.json");
@@ -981,7 +973,9 @@ describe("worktree helpers", () => {
);
it("ensure-seeded records a target shutdown diagnostic when restore fails", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-ensure-seeded-failure-"));
expect(formatWorktreeSeedFailureDiagnostic("migrations", new Error("secret connection failure")))
.toBe("Seed failed during migrations.");
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-ensure-seeded-failure-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "worktree");
@@ -998,15 +992,7 @@ describe("worktree helpers", () => {
serverPort: 3198,
databasePort: 54998,
});
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
writeSeedConfigFiles(sourceConfigPath, targetConfigPath, targetRoot, targetPaths, sourceConfig, targetConfig);
markWorktreeSeedPending({ configPath: targetConfigPath, sourceConfigPath });
await expect(
@@ -1044,7 +1030,7 @@ describe("worktree helpers", () => {
});
it("serializes concurrent ensure-seeded calls across the seed marker lock", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-ensure-seeded-lock-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-ensure-seeded-lock-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "worktree");
@@ -1061,15 +1047,7 @@ describe("worktree helpers", () => {
serverPort: 3197,
databasePort: 54997,
});
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
writeSeedConfigFiles(sourceConfigPath, targetConfigPath, targetRoot, targetPaths, sourceConfig, targetConfig);
markWorktreeSeedPending({ configPath: targetConfigPath, sourceConfigPath });
const seedDatabase = vi.fn(async () => {
@@ -1094,7 +1072,7 @@ describe("worktree helpers", () => {
});
it("records an interrupted phase before retrying to a verified terminal state", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-interrupted-seed-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-interrupted-seed-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "worktree");
@@ -1111,15 +1089,7 @@ describe("worktree helpers", () => {
serverPort: 3196,
databasePort: 54996,
});
fs.mkdirSync(path.dirname(sourceConfigPath), { recursive: true });
fs.mkdirSync(path.dirname(targetConfigPath), { recursive: true });
fs.writeFileSync(sourceConfigPath, `${JSON.stringify(sourceConfig)}\n`);
fs.writeFileSync(path.join(path.dirname(sourceConfigPath), ".env"), "PAPERCLIP_INSTANCE_ID=source\n");
fs.writeFileSync(targetConfigPath, `${JSON.stringify(targetConfig)}\n`);
fs.writeFileSync(
path.join(targetRoot, ".paperclip", ".env"),
`PAPERCLIP_HOME=${targetPaths.homeDir}\nPAPERCLIP_INSTANCE_ID=${targetPaths.instanceId}\n`,
);
writeSeedConfigFiles(sourceConfigPath, targetConfigPath, targetRoot, targetPaths, sourceConfig, targetConfig);
markWorktreeSeedPending({ configPath: targetConfigPath, sourceConfigPath });
const interrupted = readWorktreeSeedManifest(targetConfigPath)!;
fs.writeFileSync(
@@ -1147,7 +1117,7 @@ describe("worktree helpers", () => {
});
it("fails closed instead of racing to reclaim a stale seed lock", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-ensure-seeded-stale-lock-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-ensure-seeded-stale-lock-"));
try {
const targetConfigPath = path.join(tempRoot, ".paperclip", "config.json");
const lockPath = path.join(tempRoot, ".paperclip", "seed.lock");
@@ -1413,7 +1383,7 @@ describe("worktree helpers", () => {
});
it("copies the source local_encrypted secrets key into the seeded worktree instance", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-secrets-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-secrets-"));
const originalInlineMasterKey = process.env.PAPERCLIP_SECRETS_MASTER_KEY;
const originalKeyFile = process.env.PAPERCLIP_SECRETS_MASTER_KEY_FILE;
try {
@@ -1452,7 +1422,7 @@ describe("worktree helpers", () => {
});
it("writes the source inline secrets master key into the seeded worktree instance", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-secrets-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-secrets-"));
try {
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetKeyPath = path.join(tempRoot, "target", "secrets", "master.key");
@@ -1473,7 +1443,7 @@ describe("worktree helpers", () => {
});
it("creates an explicitly empty worktree without inherited signing secrets or deferred copying", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-empty-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-empty-"));
const originalCwd = process.cwd();
const originalJwt = process.env.PAPERCLIP_AGENT_JWT_SECRET;
const originalSigning = process.env.PAPERCLIP_TOOL_ACTION_SIGNING_SECRET;
@@ -1503,7 +1473,7 @@ describe("worktree helpers", () => {
});
it("persists the current agent jwt secret into the worktree env file", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-jwt-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-jwt-"));
const repoRoot = path.join(tempRoot, "repo");
const originalCwd = process.cwd();
const originalJwtSecret = process.env.PAPERCLIP_AGENT_JWT_SECRET;
@@ -1544,7 +1514,7 @@ describe("worktree helpers", () => {
});
it("preserves repo-managed worktree checkouts when --force re-runs from the source repo", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-force-preserve-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-force-preserve-"));
const repoRoot = path.join(tempRoot, "repo");
const originalCwd = process.cwd();
@@ -1585,7 +1555,7 @@ describe("worktree helpers", () => {
itEmbeddedPostgres(
"seeds a local-trusted implicit board user without a credential account",
async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-local-board-seed-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-local-board-seed-"));
const originalCwd = process.cwd();
onTestFinished(() => {
process.chdir(originalCwd);
@@ -1687,7 +1657,7 @@ describe("worktree helpers", () => {
itEmbeddedPostgres(
"seeds a lagging source whose migration application order differs from filename order",
async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-auth-seed-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-auth-seed-"));
const originalCwd = process.cwd();
onTestFinished(() => {
process.chdir(originalCwd);
@@ -1866,7 +1836,7 @@ describe("worktree helpers", () => {
);
it("avoids ports already claimed by sibling worktree instance configs", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-claimed-ports-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-claimed-ports-"));
const repoRoot = path.join(tempRoot, "repo");
const homeDir = path.join(tempRoot, ".paperclip-worktrees");
const siblingInstanceRoot = path.join(homeDir, "instances", "existing-worktree");
@@ -1947,7 +1917,7 @@ describe("worktree helpers", () => {
});
it("reserves distinct ports for postgres-mode siblings under a custom worktree parent", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-custom-parent-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-custom-parent-"));
const homeDir = path.join(tempRoot, ".paperclip-worktrees");
const customParentDir = path.join(tempRoot, "custom", "workspace-lanes");
const firstWorktreeRoot = path.join(customParentDir, "lane-one");
@@ -2002,7 +1972,7 @@ describe("worktree helpers", () => {
});
it("defaults the seed source config to the current repo-local Paperclip config", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-source-config-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-source-config-"));
const repoRoot = path.join(tempRoot, "repo");
const localConfigPath = path.join(repoRoot, ".paperclip", "config.json");
const originalCwd = process.cwd();
@@ -2027,7 +1997,7 @@ describe("worktree helpers", () => {
});
it("preserves the source config path across worktree:make cwd changes", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-source-override-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-source-override-"));
const sourceConfigPath = path.join(tempRoot, "source", "config.json");
const targetRoot = path.join(tempRoot, "target");
const originalCwd = process.cwd();
@@ -2070,7 +2040,7 @@ describe("worktree helpers", () => {
});
it("derives worktree reseed target paths from the adjacent env file", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-reseed-target-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-reseed-target-"));
const worktreeRoot = path.join(tempRoot, "repo");
const configPath = path.join(worktreeRoot, ".paperclip", "config.json");
const envPath = path.join(worktreeRoot, ".paperclip", ".env");
@@ -2102,7 +2072,7 @@ describe("worktree helpers", () => {
});
it("rejects reseed targets without worktree env metadata", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-reseed-target-missing-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-reseed-target-missing-"));
const worktreeRoot = path.join(tempRoot, "repo");
const configPath = path.join(worktreeRoot, ".paperclip", "config.json");
@@ -2127,7 +2097,7 @@ describe("worktree helpers", () => {
});
itEmbeddedPostgres("reseed preserves the current worktree ports, instance id, and branding", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-reseed-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-reseed-"));
const repoRoot = path.join(tempRoot, "repo");
const sourceRoot = path.join(tempRoot, "source");
const homeDir = path.join(tempRoot, ".paperclip-worktrees");
@@ -2232,7 +2202,7 @@ describe("worktree helpers", () => {
});
it("restores the current worktree config and instance data if reseed fails", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-reseed-rollback-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-reseed-rollback-"));
const repoRoot = path.join(tempRoot, "repo");
const sourceRoot = path.join(tempRoot, "source");
const homeDir = path.join(tempRoot, ".paperclip-worktrees");
@@ -2341,18 +2311,13 @@ describe("worktree helpers", () => {
});
it("copies shared git hooks into a linked worktree git dir", () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-hooks-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-hooks-"));
const repoRoot = path.join(tempRoot, "repo");
const worktreePath = path.join(tempRoot, "repo-feature");
try {
fs.mkdirSync(repoRoot, { recursive: true });
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.name", "Test User"], { cwd: repoRoot, stdio: "ignore" });
fs.writeFileSync(path.join(repoRoot, "README.md"), "# temp\n", "utf8");
execFileSync("git", ["add", "README.md"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["commit", "-m", "Initial commit"], { cwd: repoRoot, stdio: "ignore" });
initializeTestRepo(repoRoot);
const sourceHooksDir = path.join(repoRoot, ".git", "hooks");
const sourceHookPath = path.join(sourceHooksDir, "pre-commit");
@@ -2389,7 +2354,7 @@ describe("worktree helpers", () => {
}, 15_000);
it("creates and initializes a worktree from the top-level worktree:make command", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-make-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-make-"));
const repoRoot = path.join(tempRoot, "repo");
const fakeHome = path.join(tempRoot, "home");
const worktreePath = path.join(fakeHome, "paperclip-make-test");
@@ -2399,12 +2364,7 @@ describe("worktree helpers", () => {
try {
fs.mkdirSync(repoRoot, { recursive: true });
fs.mkdirSync(fakeHome, { recursive: true });
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.name", "Test User"], { cwd: repoRoot, stdio: "ignore" });
fs.writeFileSync(path.join(repoRoot, "README.md"), "# temp\n", "utf8");
execFileSync("git", ["add", "README.md"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["commit", "-m", "Initial commit"], { cwd: repoRoot, stdio: "ignore" });
initializeTestRepo(repoRoot);
process.chdir(repoRoot);
@@ -2424,18 +2384,13 @@ describe("worktree helpers", () => {
}, 20_000);
it("no-ops on the primary checkout unless --branch is provided", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-repair-primary-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-repair-primary-"));
const repoRoot = path.join(tempRoot, "repo");
const originalCwd = process.cwd();
try {
fs.mkdirSync(repoRoot, { recursive: true });
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.name", "Test User"], { cwd: repoRoot, stdio: "ignore" });
fs.writeFileSync(path.join(repoRoot, "README.md"), "# temp\n", "utf8");
execFileSync("git", ["add", "README.md"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["commit", "-m", "Initial commit"], { cwd: repoRoot, stdio: "ignore" });
initializeTestRepo(repoRoot);
process.chdir(repoRoot);
await worktreeRepairCommand({});
@@ -2449,7 +2404,7 @@ describe("worktree helpers", () => {
});
it("repairs the current linked worktree when Paperclip metadata is missing", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-repair-current-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-repair-current-"));
const repoRoot = path.join(tempRoot, "repo");
const worktreePath = path.join(repoRoot, ".paperclip", "worktrees", "repair-me");
const sourceConfigPath = path.join(tempRoot, "source-config.json");
@@ -2463,12 +2418,7 @@ describe("worktree helpers", () => {
try {
fs.mkdirSync(repoRoot, { recursive: true });
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.name", "Test User"], { cwd: repoRoot, stdio: "ignore" });
fs.writeFileSync(path.join(repoRoot, "README.md"), "# temp\n", "utf8");
execFileSync("git", ["add", "README.md"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["commit", "-m", "Initial commit"], { cwd: repoRoot, stdio: "ignore" });
initializeTestRepo(repoRoot);
fs.mkdirSync(path.dirname(worktreePath), { recursive: true });
execFileSync("git", ["worktree", "add", "-b", "repair-me", worktreePath, "HEAD"], {
cwd: repoRoot,
@@ -2496,7 +2446,7 @@ describe("worktree helpers", () => {
}, 20_000);
it("creates and repairs a missing branch worktree when --branch is provided", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-worktree-repair-branch-"));
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), "paperclip-worktree-repair-branch-"));
const repoRoot = path.join(tempRoot, "repo");
const sourceConfigPath = path.join(tempRoot, "source-config.json");
const worktreeHome = path.join(tempRoot, ".paperclip-worktrees");
@@ -2505,12 +2455,7 @@ describe("worktree helpers", () => {
try {
fs.mkdirSync(repoRoot, { recursive: true });
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["config", "user.name", "Test User"], { cwd: repoRoot, stdio: "ignore" });
fs.writeFileSync(path.join(repoRoot, "README.md"), "# temp\n", "utf8");
execFileSync("git", ["add", "README.md"], { cwd: repoRoot, stdio: "ignore" });
execFileSync("git", ["commit", "-m", "Initial commit"], { cwd: repoRoot, stdio: "ignore" });
initializeTestRepo(repoRoot);
fs.writeFileSync(sourceConfigPath, JSON.stringify(buildSourceConfig(), null, 2), "utf8");
process.chdir(repoRoot);