@clipboard-health/groundcrew 4.52.10 → 4.52.12
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/crew.config.example.ts +5 -0
- package/dist/commands/openWorkspace.d.ts.map +1 -1
- package/dist/commands/openWorkspace.js +7 -4
- package/dist/commands/resumeWorkspace.d.ts.map +1 -1
- package/dist/commands/resumeWorkspace.js +1 -0
- package/dist/commands/setupWorkspace.d.ts.map +1 -1
- package/dist/commands/setupWorkspace.js +7 -4
- package/dist/lib/agentLaunch.d.ts +2 -0
- package/dist/lib/agentLaunch.d.ts.map +1 -1
- package/dist/lib/agentLaunch.js +1 -0
- package/dist/lib/buildSecrets.d.ts +1 -0
- package/dist/lib/buildSecrets.d.ts.map +1 -1
- package/dist/lib/config.d.ts +11 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +22 -6
- package/dist/lib/launchCommand.d.ts +7 -1
- package/dist/lib/launchCommand.d.ts.map +1 -1
- package/dist/lib/launchCommand.js +12 -7
- package/dist/lib/stagedLaunch.d.ts +11 -1
- package/dist/lib/stagedLaunch.d.ts.map +1 -1
- package/dist/lib/stagedLaunch.js +9 -0
- package/docs/configuration.md +1 -0
- package/docs/credentials.md +12 -0
- package/package.json +7 -8
package/crew.config.example.ts
CHANGED
|
@@ -195,6 +195,11 @@ export default {
|
|
|
195
195
|
// // sandboxed code launch commands outside the sandbox.
|
|
196
196
|
// local: { safehouse: { appendProfile: ["~/.config/groundcrew/mytool.sb"] } },
|
|
197
197
|
//
|
|
198
|
+
// // Build secrets (NPM_TOKEN, BUF_TOKEN) the agent keeps after
|
|
199
|
+
// // prepareWorktree, e.g. to reinstall private packages mid-task. Only list
|
|
200
|
+
// // read-scoped tokens. Supported by the safehouse and sdx runners.
|
|
201
|
+
// local: { agentBuildSecrets: ["NPM_TOKEN"] },
|
|
202
|
+
//
|
|
198
203
|
// // Groundcrew does not create or authenticate sdx sandboxes. For an sdx
|
|
199
204
|
// // agent, create the matching sandbox yourself before first launch:
|
|
200
205
|
// // sbx create --name groundcrew-claude claude ~/dev/groundcrew
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/openWorkspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBtF,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA0KD,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"openWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/openWorkspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBtF,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA0KD,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA8Hf;AA4ID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAE3E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE"}
|
|
@@ -7,7 +7,7 @@ import { resolvePullRequest } from "../lib/pullRequests.js";
|
|
|
7
7
|
import { resolveRepositoryPreparationCommands } from "../lib/repositoryHooks.js";
|
|
8
8
|
import { recordRunState, readRunState } from "../lib/runState.js";
|
|
9
9
|
import { seedLaunchWorkspaceTrust } from "../lib/seedLaunchWorkspaceTrust.js";
|
|
10
|
-
import { removeStagedPrompt,
|
|
10
|
+
import { removeStagedPrompt, stageBuildSecretsForLaunch, stagePromptText, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
|
|
11
11
|
import { normalizePlainTaskId } from "../lib/taskId.js";
|
|
12
12
|
import { debug, errorMessage, log, okMark } from "../lib/util.js";
|
|
13
13
|
import { failIfWorkspaceAlreadyLive } from "../lib/workspaceLiveness.js";
|
|
@@ -169,9 +169,11 @@ export async function openWorkspace(config, options) {
|
|
|
169
169
|
repository,
|
|
170
170
|
worktreeDir: launchDir,
|
|
171
171
|
});
|
|
172
|
-
const secretsFile =
|
|
173
|
-
|
|
174
|
-
:
|
|
172
|
+
const secretsFile = stageBuildSecretsForLaunch({
|
|
173
|
+
promptDir: stagedPrompt.directory,
|
|
174
|
+
hasPreparationCommand: prepareWorktreeCommand !== undefined || prepareWorktreeUnsandboxedCommand !== undefined,
|
|
175
|
+
agentBuildSecrets: config.local.agentBuildSecrets,
|
|
176
|
+
});
|
|
175
177
|
seedLaunchWorkspaceTrust({
|
|
176
178
|
agentCommandName: inferAgentCommandName(definition.cmd),
|
|
177
179
|
launchDir,
|
|
@@ -191,6 +193,7 @@ export async function openWorkspace(config, options) {
|
|
|
191
193
|
workspaceKind,
|
|
192
194
|
readOnlyDirs: config.local.readOnlyDirs,
|
|
193
195
|
safehouse: config.local.safehouse,
|
|
196
|
+
agentBuildSecrets: config.local.agentBuildSecrets,
|
|
194
197
|
omitPromptArgument,
|
|
195
198
|
});
|
|
196
199
|
cleanupAgentLaunch = launch.cleanup;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAwBzF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoMD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAwBzF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoMD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAiIf;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
|
|
@@ -225,6 +225,7 @@ export async function resumeWorkspace(config, options) {
|
|
|
225
225
|
}),
|
|
226
226
|
taskSourceWritePaths,
|
|
227
227
|
safehouse: config.local.safehouse,
|
|
228
|
+
agentBuildSecrets: config.local.agentBuildSecrets,
|
|
228
229
|
});
|
|
229
230
|
cleanupAgentLaunch = launch.cleanup;
|
|
230
231
|
const launchCmd = stageWorkspaceLaunchCommand(stagedPrompt.directory, launch.command);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBnE,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAWxF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBnE,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAWxF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CA8Jf;AAiOD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CAyDf"}
|
|
@@ -7,7 +7,7 @@ import { resolveRepositoryPreparationCommands } from "../lib/repositoryHooks.js"
|
|
|
7
7
|
import { recordRunState } from "../lib/runState.js";
|
|
8
8
|
import { seedLaunchWorkspaceTrust } from "../lib/seedLaunchWorkspaceTrust.js";
|
|
9
9
|
import { sourceSupportsMarkDone } from "../lib/sourceCapabilities.js";
|
|
10
|
-
import { removeStagedPrompt,
|
|
10
|
+
import { removeStagedPrompt, stageBuildSecretsForLaunch, stagePromptFromTemplate, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
|
|
11
11
|
import { taskSourceWritePathsForCompletion } from "../lib/taskSourceFilesystem.js";
|
|
12
12
|
import { naturalIdFromCanonical } from "../lib/taskSource.js";
|
|
13
13
|
import { debug, errorMessage, log, okMark } from "../lib/util.js";
|
|
@@ -95,9 +95,11 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
95
95
|
if (!shouldPrepareWorktree) {
|
|
96
96
|
log(`Skipping prepareWorktree for ${task} (task policy)`);
|
|
97
97
|
}
|
|
98
|
-
const secretsFile =
|
|
99
|
-
|
|
100
|
-
:
|
|
98
|
+
const secretsFile = stageBuildSecretsForLaunch({
|
|
99
|
+
promptDir,
|
|
100
|
+
hasPreparationCommand: prepareWorktreeCommand !== undefined || prepareWorktreeUnsandboxedCommand !== undefined,
|
|
101
|
+
agentBuildSecrets: config.local.agentBuildSecrets,
|
|
102
|
+
});
|
|
101
103
|
const completionTaskId = options.completionTaskId ?? task;
|
|
102
104
|
const completionMarkDoneSupported = options.completionMarkDoneSupported ?? true;
|
|
103
105
|
const taskSourceWritePaths = runner === "safehouse"
|
|
@@ -131,6 +133,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
131
133
|
}),
|
|
132
134
|
taskSourceWritePaths,
|
|
133
135
|
safehouse: config.local.safehouse,
|
|
136
|
+
agentBuildSecrets: config.local.agentBuildSecrets,
|
|
134
137
|
});
|
|
135
138
|
cleanupAgentLaunch = launch.cleanup;
|
|
136
139
|
const launchCmd = stageWorkspaceLaunchCommand(promptDir, launch.command);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BuildSecretName } from "./buildSecrets.ts";
|
|
1
2
|
import { type LocalRunner, type AgentDefinition, type NetworkEgressSetting, type ResolvedConfig } from "./config.ts";
|
|
2
3
|
import { type WorkerEnvironment } from "./launchCommand.ts";
|
|
3
4
|
import type { WorkspaceKind } from "./workspaceAdapter.ts";
|
|
@@ -22,6 +23,7 @@ export declare function composeAgentLaunch(input: {
|
|
|
22
23
|
workerEnvironment?: WorkerEnvironment | undefined;
|
|
23
24
|
omitPromptArgument?: boolean | undefined;
|
|
24
25
|
taskSourceWritePaths?: readonly string[] | undefined;
|
|
26
|
+
agentBuildSecrets?: readonly BuildSecretName[] | undefined;
|
|
25
27
|
safehouse: ResolvedConfig["local"]["safehouse"];
|
|
26
28
|
readOnlyDirs?: readonly string[] | undefined;
|
|
27
29
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAW5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,oBAAoB,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,iCAAiC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAClD,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACrD,iBAAiB,CAAC,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,CAAC;IAC3D,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,mBAAmB,CAgDtB;AAqHD,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,iFAAiF;IACjF,aAAa,EAAE,oBAAoB,CAAC;IACpC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAsD/B;AAwBD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
|
package/dist/lib/agentLaunch.js
CHANGED
|
@@ -49,6 +49,7 @@ export function composeAgentLaunch(input) {
|
|
|
49
49
|
safehouseAddDirs: input.runner === "safehouse" ? resolveSafehouseAddDirs(input.worktreeDir) : undefined,
|
|
50
50
|
safehouseAgentAddDirs: input.runner === "safehouse" ? (input.taskSourceWritePaths ?? []) : undefined,
|
|
51
51
|
safehouse: input.safehouse,
|
|
52
|
+
agentBuildSecrets: input.agentBuildSecrets,
|
|
52
53
|
// Safehouse rejects nonexistent --add-dirs-ro paths, so drop absent ones.
|
|
53
54
|
safehouseAgentAddDirsReadOnly: input.runner === "safehouse" ? (input.readOnlyDirs ?? []).filter(existsSync) : undefined,
|
|
54
55
|
safehouseAgentIntegration,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildSecrets.d.ts","sourceRoot":"","sources":["../../src/lib/buildSecrets.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,kBAAkB,YAAI,WAAW,EAAE,WAAW,CAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"buildSecrets.d.ts","sourceRoot":"","sources":["../../src/lib/buildSecrets.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,kBAAkB,YAAI,WAAW,EAAE,WAAW,CAAU,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { LinearAdapterConfig } from "./adapters/linear/schema.ts";
|
|
2
2
|
import type { ShellAdapterConfig } from "./adapters/shell/schema.ts";
|
|
3
3
|
import type { TodoTxtAdapterConfig } from "./adapters/todo-txt/schema.ts";
|
|
4
|
-
|
|
4
|
+
import { type BuildSecretName } from "./buildSecrets.ts";
|
|
5
|
+
export { BUILD_SECRET_NAMES, type BuildSecretName } from "./buildSecrets.ts";
|
|
5
6
|
export declare const WORKER_ENVIRONMENT_NAMES: readonly ["GROUNDCREW_TASK_ID", "GROUNDCREW_COMPLETE"];
|
|
6
7
|
/**
|
|
7
8
|
* Authoring shape for a manifest-backed (discovered) task source: enable by
|
|
@@ -346,6 +347,14 @@ export interface Config {
|
|
|
346
347
|
* unrestricted network egress. `sdx`/`none` ignore this setting.
|
|
347
348
|
*/
|
|
348
349
|
networkEgress?: NetworkEgressSetting;
|
|
350
|
+
/**
|
|
351
|
+
* Build secrets (`BUILD_SECRET_NAMES` entries) that stay in the launched
|
|
352
|
+
* agent's environment instead of being cleared after prepareWorktree, e.g.
|
|
353
|
+
* so an agent can reinstall private packages mid-task. Opt in only for
|
|
354
|
+
* read-scoped tokens. Supported by the `safehouse` and `sdx` runners.
|
|
355
|
+
* Defaults to none.
|
|
356
|
+
*/
|
|
357
|
+
agentBuildSecrets?: BuildSecretName[];
|
|
349
358
|
/**
|
|
350
359
|
* Safehouse sandbox tuning. Consumed only by the `safehouse` runner; other
|
|
351
360
|
* runners ignore it.
|
|
@@ -464,6 +473,7 @@ export interface ResolvedConfig {
|
|
|
464
473
|
* `"allowlisted"`. Only the safehouse runner consumes this today.
|
|
465
474
|
*/
|
|
466
475
|
networkEgress: NetworkEgressSetting;
|
|
476
|
+
agentBuildSecrets: readonly BuildSecretName[];
|
|
467
477
|
/**
|
|
468
478
|
* Resolved Safehouse tuning. Always present; both lists default to `[]`.
|
|
469
479
|
* Only the safehouse runner consumes it.
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.js
CHANGED
|
@@ -61,6 +61,7 @@ function normalizeLocal(userLocal) {
|
|
|
61
61
|
return {
|
|
62
62
|
runner: normalizeLocalRunner(userLocal?.runner, "local.runner") ?? "auto",
|
|
63
63
|
networkEgress: normalizeNetworkEgress(userLocal?.networkEgress, "local.networkEgress") ?? "allowlisted",
|
|
64
|
+
agentBuildSecrets: normalizeAgentBuildSecrets(userLocal?.agentBuildSecrets, "local.agentBuildSecrets"),
|
|
64
65
|
safehouse: normalizeSafehouse(userLocal?.safehouse, "local.safehouse"),
|
|
65
66
|
readOnlyDirs: normalizeReadOnlyDirs(userLocal?.readOnlyDirs),
|
|
66
67
|
};
|
|
@@ -348,14 +349,10 @@ function validatePreLaunchEnv(agentName, value) {
|
|
|
348
349
|
if (typeof entry !== "string" || !ENV_VAR_NAME_PATTERN.test(entry)) {
|
|
349
350
|
fail(`${configPath}[${index}] must be a POSIX env var name matching ${ENV_VAR_NAME_PATTERN.source} (got ${JSON.stringify(entry)})`);
|
|
350
351
|
}
|
|
351
|
-
// Build secrets are sourced into the host launch shell, forwarded only to
|
|
352
|
-
// the Safehouse *prepareWorktree* wrap, and `unset` on the host before the agent
|
|
353
|
-
// wrap is exec'd. Listing one here would silently never reach the agent —
|
|
354
|
-
// fail loudly so the operator picks a different name (or removes the
|
|
355
|
-
// entry) instead of debugging a missing env var at runtime.
|
|
356
352
|
if (BUILD_SECRET_NAMES.includes(entry)) {
|
|
357
353
|
fail(`${configPath}[${index}] cannot be a BUILD_SECRET_NAMES entry (${BUILD_SECRET_NAMES.join(", ")}); ` +
|
|
358
|
-
"those are unset on the host before the agent wrap is exec'd, so forwarding them via --env-pass would be a no-op."
|
|
354
|
+
"those are unset on the host before the agent wrap is exec'd, so forwarding them via --env-pass would be a no-op. " +
|
|
355
|
+
"To keep a build secret in the agent's environment, list it in local.agentBuildSecrets.");
|
|
359
356
|
}
|
|
360
357
|
if (WORKER_ENVIRONMENT_NAMES.includes(entry)) {
|
|
361
358
|
fail(`${configPath}[${index}] cannot be a managed worker environment name (${WORKER_ENVIRONMENT_NAMES.join(", ")}); ` +
|
|
@@ -412,6 +409,25 @@ function normalizeNetworkEgress(value, configKey) {
|
|
|
412
409
|
}
|
|
413
410
|
return value;
|
|
414
411
|
}
|
|
412
|
+
function isBuildSecretName(value) {
|
|
413
|
+
return BUILD_SECRET_NAMES.some((name) => name === value);
|
|
414
|
+
}
|
|
415
|
+
function normalizeAgentBuildSecrets(value, configKey) {
|
|
416
|
+
if (value === undefined) {
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
419
|
+
if (!Array.isArray(value)) {
|
|
420
|
+
fail(`${configKey} must be an array of build secret names (got ${JSON.stringify(value)})`);
|
|
421
|
+
}
|
|
422
|
+
const names = [];
|
|
423
|
+
for (const [index, entry] of value.entries()) {
|
|
424
|
+
if (!isBuildSecretName(entry)) {
|
|
425
|
+
fail(`${configKey}[${index}] must be one of ${BUILD_SECRET_NAMES.join(", ")} (got ${JSON.stringify(entry)})`);
|
|
426
|
+
}
|
|
427
|
+
names.push(entry);
|
|
428
|
+
}
|
|
429
|
+
return [...new Set(names)];
|
|
430
|
+
}
|
|
415
431
|
const SAFEHOUSE_FEATURE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
416
432
|
function normalizeSafehouse(value, configKey) {
|
|
417
433
|
if (value === undefined) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LocalRunner, type AgentDefinition, type NetworkEgressSetting, type ResolvedConfig } from "./config.ts";
|
|
1
|
+
import { type BuildSecretName, type LocalRunner, type AgentDefinition, type NetworkEgressSetting, type ResolvedConfig } from "./config.ts";
|
|
2
2
|
export { shellSingleQuote } from "./shell.ts";
|
|
3
3
|
/**
|
|
4
4
|
* Return a copy of `definition` whose `cmd` has the agent's `resumeArgs`
|
|
@@ -92,6 +92,12 @@ interface LaunchCommandArguments {
|
|
|
92
92
|
* agent process never inherits them.
|
|
93
93
|
*/
|
|
94
94
|
secretsFile?: string | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Build-secret names the operator opted to keep in the agent's environment
|
|
97
|
+
* (`local.agentBuildSecrets`). Honored by the safehouse wrap and sdx runner;
|
|
98
|
+
* the unwrapped host path rejects a non-empty list.
|
|
99
|
+
*/
|
|
100
|
+
agentBuildSecrets?: readonly BuildSecretName[] | undefined;
|
|
95
101
|
/**
|
|
96
102
|
* Optional repo-preparation hook resolved by the caller from the freshly
|
|
97
103
|
* created worktree's `.groundcrew/config.json`, falling back to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchCommand.d.ts","sourceRoot":"","sources":["../../src/lib/launchCommand.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"launchCommand.d.ts","sourceRoot":"","sources":["../../src/lib/launchCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,8 +77,9 @@ function sourceSecretsLine(secretsFile) {
|
|
|
77
77
|
function unsetEnvironmentLine(names) {
|
|
78
78
|
return `unset ${[...new Set(names)].join(" ")}`;
|
|
79
79
|
}
|
|
80
|
-
function
|
|
81
|
-
|
|
80
|
+
function unsetSecretsLines(retained) {
|
|
81
|
+
const names = BUILD_SECRET_NAMES.filter((name) => !retained.includes(name));
|
|
82
|
+
return names.length === 0 ? [] : [unsetEnvironmentLine(names)];
|
|
82
83
|
}
|
|
83
84
|
function safehouseClearanceWrapperCommand() {
|
|
84
85
|
return `CLEARANCE_ALLOW_HOSTS_FILES=${shellSingleQuote(clearanceAllowHostsFilesFromEnvironment())} ${shellSingleQuote(SAFEHOUSE_CLEARANCE_WRAPPER_PATH)}`;
|
|
@@ -305,6 +306,9 @@ export function buildLaunchCommand(arguments_) {
|
|
|
305
306
|
// inject into. Fail loudly instead of silently dropping the contract.
|
|
306
307
|
throw new Error("preLaunchEnv cannot be injected when 'cmd' starts with 'safehouse' — your cmd owns the wrap, so add the names to its own '--env-pass=' flag, or drop the 'safehouse' prefix from 'cmd' to let groundcrew compose the flag for you.");
|
|
307
308
|
}
|
|
309
|
+
if ((arguments_.agentBuildSecrets ?? []).length > 0) {
|
|
310
|
+
throw new Error("local.agentBuildSecrets is not supported when the agent runs outside groundcrew's Safehouse wrap (runner 'none' or a 'cmd' starting with 'safehouse'). Use runner 'safehouse' or 'sdx', or clear local.agentBuildSecrets.");
|
|
311
|
+
}
|
|
308
312
|
if (arguments_.workerEnvironment !== undefined && arguments_.runner === "safehouse") {
|
|
309
313
|
throw new Error("workerEnvironment cannot be injected when 'cmd' starts with 'safehouse' — your cmd owns the wrap, so add GROUNDCREW_TASK_ID,GROUNDCREW_COMPLETE to its own '--env-pass=' flag, or drop the 'safehouse' prefix from 'cmd' to let groundcrew compose the flag for you.");
|
|
310
314
|
}
|
|
@@ -347,7 +351,7 @@ function buildUnwrappedHostLaunchCommand(arguments_) {
|
|
|
347
351
|
lines.push(prepareWorktreeWithStatusReporting(arguments_.prepareWorktreeCommand));
|
|
348
352
|
}
|
|
349
353
|
if (arguments_.secretsFile !== undefined) {
|
|
350
|
-
lines.push(
|
|
354
|
+
lines.push(...unsetSecretsLines([]));
|
|
351
355
|
}
|
|
352
356
|
lines.push(...workerEnvironmentExports(arguments_.workerEnvironment), ...preLaunchPromptAndExec({
|
|
353
357
|
definition: arguments_.definition,
|
|
@@ -399,12 +403,13 @@ function buildSafehouseLaunchCommand(arguments_) {
|
|
|
399
403
|
].join("; ");
|
|
400
404
|
// Split --env-pass per wrap: the prepareWorktree wrap only needs build secrets (so
|
|
401
405
|
// `npm install` etc. can authenticate); the agent wrap only needs the
|
|
402
|
-
// user's preLaunchEnv
|
|
403
|
-
//
|
|
406
|
+
// user's preLaunchEnv plus any build secrets opted in via
|
|
407
|
+
// local.agentBuildSecrets (the rest are `unset` on the host between the wraps). Keeps preLaunch
|
|
404
408
|
// credentials out of the profile-neutral prepare phase — see PR #128.
|
|
405
409
|
// Trailing space keeps each flag separated from the next argv token.
|
|
406
410
|
const prepareWorktreeEnvPassFlag = arguments_.secretsFile === undefined ? "" : `--env-pass=${BUILD_SECRET_NAMES.join(",")} `;
|
|
407
411
|
const agentEnvPassFlag = envPassFlag([
|
|
412
|
+
...(arguments_.secretsFile === undefined ? [] : (arguments_.agentBuildSecrets ?? [])),
|
|
408
413
|
...(arguments_.definition.preLaunchEnv ?? []),
|
|
409
414
|
...workerEnvironmentNames(arguments_.workerEnvironment),
|
|
410
415
|
...(safehouseAgentIntegration?.envPass ?? []),
|
|
@@ -468,7 +473,7 @@ function buildSafehouseLaunchCommand(arguments_) {
|
|
|
468
473
|
lines.push(`${safehouseWrapper} ${safehouseAddDirsFlag}${prepareWorktreeEnvPassFlag}sh -c ${shellSingleQuote(prepareWorktreeCommand)}`);
|
|
469
474
|
}
|
|
470
475
|
if (arguments_.secretsFile !== undefined) {
|
|
471
|
-
lines.push(
|
|
476
|
+
lines.push(...unsetSecretsLines(arguments_.agentBuildSecrets ?? []));
|
|
472
477
|
}
|
|
473
478
|
lines.push(...workerEnvironmentExports(arguments_.workerEnvironment), `_safehouse_shim_dir=$(mktemp -d "\${TMPDIR:-/tmp}/groundcrew-safehouse-XXXXXX")`, shimAndPromptTrap, `_safehouse_shim="$_safehouse_shim_dir/${safehouseCommandName}"`, `ln -s /bin/sh "$_safehouse_shim"`,
|
|
474
479
|
// Safehouse selects an agent profile from the wrapped command's basename.
|
|
@@ -564,7 +569,7 @@ function buildSdxLaunchCommand(arguments_) {
|
|
|
564
569
|
innerParts.push(prepareWorktreeCommand);
|
|
565
570
|
}
|
|
566
571
|
if (arguments_.secretsFile !== undefined) {
|
|
567
|
-
innerParts.push(
|
|
572
|
+
innerParts.push(...unsetSecretsLines(arguments_.agentBuildSecrets ?? []));
|
|
568
573
|
}
|
|
569
574
|
innerParts.push(...workerEnvironmentExports(arguments_.workerEnvironment), agentCommand);
|
|
570
575
|
const innerCommand = innerParts.join("; ");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ResolvedConfig } from "./config.ts";
|
|
1
|
+
import { type BuildSecretName, type ResolvedConfig } from "./config.ts";
|
|
2
2
|
export interface StagedPrompt {
|
|
3
3
|
directory: string;
|
|
4
4
|
file: string;
|
|
@@ -27,6 +27,16 @@ export declare function stagePromptFromTemplate(input: {
|
|
|
27
27
|
* has nothing to forward, leaving the launch command unchanged.
|
|
28
28
|
*/
|
|
29
29
|
export declare function stageBuildSecrets(promptDir: string): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Stage build secrets only when something in the launch consumes them: a
|
|
32
|
+
* prepareWorktree command, or an agent that retains them via
|
|
33
|
+
* `local.agentBuildSecrets`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function stageBuildSecretsForLaunch(arguments_: {
|
|
36
|
+
promptDir: string;
|
|
37
|
+
hasPreparationCommand: boolean;
|
|
38
|
+
agentBuildSecrets: readonly BuildSecretName[];
|
|
39
|
+
}): string | undefined;
|
|
30
40
|
export declare function stageWorkspaceLaunchCommand(promptDir: string, command: string): string;
|
|
31
41
|
export declare function removeStagedPrompt(directory: string): void;
|
|
32
42
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stagedLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/stagedLaunch.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"stagedLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/stagedLaunch.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAI5F,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC,EAAE,MAAM,CAAC;CAC1C;AAWD,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,YAAY,CAKf;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,uBAAuB,CAAC;CACpC,GAAG,YAAY,CAMf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAevE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,iBAAiB,EAAE,SAAS,eAAe,EAAE,CAAC;CAC/C,GAAG,MAAM,GAAG,SAAS,CAIrB;AAQD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtF;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE1D"}
|
package/dist/lib/stagedLaunch.js
CHANGED
|
@@ -46,6 +46,15 @@ export function stageBuildSecrets(promptDir) {
|
|
|
46
46
|
writeFileSync(secretsFile, `${lines.join("\n")}\n`, { mode: 0o600 });
|
|
47
47
|
return secretsFile;
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Stage build secrets only when something in the launch consumes them: a
|
|
51
|
+
* prepareWorktree command, or an agent that retains them via
|
|
52
|
+
* `local.agentBuildSecrets`.
|
|
53
|
+
*/
|
|
54
|
+
export function stageBuildSecretsForLaunch(arguments_) {
|
|
55
|
+
const needsBuildSecrets = arguments_.hasPreparationCommand || arguments_.agentBuildSecrets.length > 0;
|
|
56
|
+
return needsBuildSecrets ? stageBuildSecrets(arguments_.promptDir) : undefined;
|
|
57
|
+
}
|
|
49
58
|
function stageLaunchScript(promptDir, command) {
|
|
50
59
|
const launcherFile = path.join(promptDir, "launch.sh");
|
|
51
60
|
writeFileSync(launcherFile, `#!/usr/bin/env bash\n${command}\n`, { mode: 0o700 });
|
package/docs/configuration.md
CHANGED
|
@@ -356,6 +356,7 @@ and hook contract.
|
|
|
356
356
|
| `workspaceKind` | `"auto"` | Terminal session manager. `"auto"` picks `cmux` when on PATH, else `tmux`. Set to `"cmux"`, `"tmux"`, or `"zellij"` to fail loudly when the chosen backend is missing. |
|
|
357
357
|
| `local.runner` | `"auto"` | Local isolation backend. `"auto"` uses `safehouse` on macOS and `sdx` on Linux/WSL. Explicit: `"safehouse"`, `"sdx"`, `"none"`. `"none"` is never picked implicitly. |
|
|
358
358
|
| `local.networkEgress` | `"allowlisted"` | Network egress posture. With `local.runner: "safehouse"`, `"allowlisted"` wraps with Clearance and `"open"` keeps the Safehouse filesystem sandbox while opening network egress. Ignored by `sdx` and `none`. |
|
|
359
|
+
| `local.agentBuildSecrets` | `[]` | Build secrets (`NPM_TOKEN`, `BUF_TOKEN`) that stay in the agent's environment instead of being cleared after `prepareWorktree`, so it can reinstall private packages mid-task. Opt in only for read-scoped tokens. Unknown names are rejected. Supported by `safehouse` and `sdx`; `none` or a `safehouse`-prefixed `cmd` fails the launch. See [Build-Time Secrets](./credentials.md#build-time-secrets). |
|
|
359
360
|
| `local.readOnlyDirs` | `~/.config/tfenv` | Host directories re-opened read-only inside the Safehouse sandbox, for toolchains the profile masks but does not re-open. `~` is expanded. Defaults to tfenv's config root so `terraform`/`tfenv` work in the sandbox; set your own list to add or replace entries. Ignored by `sdx` and `none`. |
|
|
360
361
|
| `logging.file` | XDG state path | Append-mode log file. `log()` / `logEvent()` tee here in addition to stdout. Defaults to `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log`. |
|
|
361
362
|
| `cmux.prStages.enabled` | `false` | Opt-in: paints each task's cmux sidebar with its pull request's review stage (`crew_stage`) and gating labels (`crew_labels`) once per watch tick. Only takes effect when the resolved `workspaceKind` is `cmux`; other backends no-op. The ticket id (`crew_ticket`) is written for every matched cmux task workspace regardless of this flag, so sidebars that read `crew_ticket` work whether or not PR-stage sync is enabled. Manage the gating labels with `crew stage label-add`/`label-remove`, or run a pass on demand with `crew stage refresh`. |
|
package/docs/credentials.md
CHANGED
|
@@ -62,6 +62,18 @@ For each task:
|
|
|
62
62
|
|
|
63
63
|
Net effect: by the time the agent process exists, the values are gone from the environment and the file is gone from disk.
|
|
64
64
|
|
|
65
|
+
### Letting the agent keep a build secret
|
|
66
|
+
|
|
67
|
+
By default an agent that reinstalls a private package mid-task cannot authenticate. To keep a build secret in the agent's environment, list it in `local.agentBuildSecrets`:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
local: {
|
|
71
|
+
agentBuildSecrets: ["NPM_TOKEN"],
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Listed names are skipped by the post-`prepareWorktree` unset and forwarded to the agent wrap (`--env-pass` under `safehouse`; kept in the sandbox shell under `sdx`). Unlisted names are still removed. `preLaunch` still never sees build secrets. Only list read-scoped tokens: the agent can read and exfiltrate anything it receives. Not supported with `local.runner: "none"` or a `cmd` that starts with `safehouse`; launch fails loudly.
|
|
76
|
+
|
|
65
77
|
</details>
|
|
66
78
|
|
|
67
79
|
## Per-Session Credentials
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "4.52.
|
|
3
|
+
"version": "4.52.12",
|
|
4
4
|
"description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle and usage tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -62,33 +62,32 @@
|
|
|
62
62
|
"lint": "oxlint --config config/oxlint.config.ts --deny-warnings --ignore-pattern 'v2/**'",
|
|
63
63
|
"markdown:lint": "markdownlint-cli2 --config config/markdownlint-cli2.jsonc",
|
|
64
64
|
"prepack": "node --run build",
|
|
65
|
-
"prepare": "husky",
|
|
66
|
-
"sync-ai-rules": "
|
|
65
|
+
"prepare": "husky && node --run sync-ai-rules",
|
|
66
|
+
"sync-ai-rules": "npm exec --yes --package=@clipboard-health/engineering-practices@latest -- engineering-practices-sync common || true",
|
|
67
67
|
"syncpack:lint": "syncpack lint --config config/syncpack.config.ts",
|
|
68
68
|
"test": "vitest run --coverage",
|
|
69
69
|
"verify": "node scripts/verifyAll.mts"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@clipboard-health/clearance": "1.8.3",
|
|
73
|
-
"@linear/sdk": "97.
|
|
73
|
+
"@linear/sdk": "97.1.0",
|
|
74
74
|
"agent-trust": "1.0.0",
|
|
75
75
|
"cosmiconfig": "10.0.1",
|
|
76
76
|
"tslib": "2.8.1",
|
|
77
77
|
"zod": "4.6.5"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@clipboard-health/ai-rules": "2.50.17",
|
|
81
80
|
"@clipboard-health/oxlint-config": "1.14.3",
|
|
82
81
|
"@nx/js": "23.1.0",
|
|
83
82
|
"@tsconfig/node24": "24.0.5",
|
|
84
83
|
"@tsconfig/strictest": "2.0.8",
|
|
85
|
-
"@types/node": "26.6.
|
|
84
|
+
"@types/node": "26.6.4",
|
|
86
85
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
87
86
|
"@vitest/coverage-v8": "5.0.3",
|
|
88
87
|
"dependency-cruiser": "18.5.0",
|
|
89
88
|
"husky": "9.1.7",
|
|
90
89
|
"jscpd": "5.4.0",
|
|
91
|
-
"knip": "6.
|
|
90
|
+
"knip": "6.40.0",
|
|
92
91
|
"lint-staged": "17.6.0",
|
|
93
92
|
"markdownlint-cli2": "0.23.3",
|
|
94
93
|
"nx": "23.1.0",
|
|
@@ -96,7 +95,7 @@
|
|
|
96
95
|
"oxlint": "1.78.0",
|
|
97
96
|
"oxlint-tsgolint": "7.0.2003",
|
|
98
97
|
"syncpack": "15.3.3",
|
|
99
|
-
"vite": "8.3.
|
|
98
|
+
"vite": "8.3.4",
|
|
100
99
|
"vitest": "5.0.3"
|
|
101
100
|
},
|
|
102
101
|
"engines": {
|