Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ cstack inspect
cstack inspect <run-id> --interactive
```

By default, `cstack` uses `danger-full-access` and allows direct source execution for `build`, `ship`, and `deliver`. Use `--safe` on a run when you want that invocation to fall back to `workspace-write` plus clean-worktree execution for defaulted dirty-worktree settings.
By default, `cstack` uses `workspace-write` and isolated execution checkouts for `build`, `ship`, and `deliver`. Use `--allow-dirty` when you explicitly want direct source execution for a run.

While a run is active in a normal terminal, `cstack` renders a bounded ANSI dashboard instead of endlessly appending log lines.

Expand Down Expand Up @@ -551,8 +551,8 @@ Notes:

- `command` can point at the installed `codex` binary or a script path for testing.
- `sandbox`, `profile`, `model`, and `extraArgs` are passed through to Codex launches.
- By default, `sandbox` resolves to `danger-full-access`, and `workflows.build.allowDirty`, `workflows.ship.allowDirty`, and `workflows.deliver.allowDirty` resolve to `true`.
- Use `--safe` when you want one run to fall back to `workspace-write` and clean-worktree execution for defaulted `allowDirty` values.
- By default, `sandbox` resolves to `workspace-write`, and `workflows.build.allowDirty`, `workflows.ship.allowDirty`, and `workflows.deliver.allowDirty` resolve to `false`.
- Use `--allow-dirty` when you want one run to execute directly in the source checkout.
- If repo or user config explicitly sets `sandbox` or `allowDirty`, that explicit config wins over `--safe`.
- `--allow-all` is deprecated and currently accepted as a temporary no-op.
- `workflows.build.mode` selects `interactive` or `exec`; interactive is the default for build runs.
Expand Down
2 changes: 1 addition & 1 deletion src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export async function runBuild(cwd: string, args: string[] = []): Promise<string
`Mode: requested=${requestedMode} observed=${execution.observedMode}`,
`Status: ${runRecord.status}`,
execution.result.sessionId ? `Session: ${execution.result.sessionId}` : "Session: not observed",
`Execution policy: ${policy.safe ? "dangerous default disabled via --safe" : "default dangerous execution"}`,
`Execution policy: ${policy.safe ? "safe overrides applied via --safe" : "default execution policy"}`,
`Execution checkout: ${executionCheckout.record.execution.kind} @ ${executionCheckout.record.execution.cwd}`,
`Source snapshot: ${executionCheckout.record.source.branch} ${executionCheckout.record.source.commit}`,
executionCheckout.record.source.dirtyFiles.length > 0 && !allowDirty
Expand Down
2 changes: 1 addition & 1 deletion src/commands/deliver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ export async function runDeliver(cwd: string, args: string[] = [], hooks: Delive
`Mode: requested=${requestedMode} observed=${execution.buildExecution.observedMode}`,
`Status: ${finalRunRecord.status}`,
buildSession.sessionId ? `Build session: ${buildSession.sessionId}` : "Build session: not observed",
`Execution policy: ${policy.safe ? "dangerous default disabled via --safe" : "default dangerous execution"}`,
`Execution policy: ${policy.safe ? "safe overrides applied via --safe" : "default execution policy"}`,
`Execution checkout: ${executionCheckout.record.execution.kind} @ ${executionCheckout.record.execution.cwd}`,
`Source snapshot: ${executionCheckout.record.source.branch} ${executionCheckout.record.source.commit}`,
executionCheckout.record.source.dirtyFiles.length > 0 && !allowDirty
Expand Down
2 changes: 1 addition & 1 deletion src/commands/ship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ export async function runShip(cwd: string, args: string[] = [], hooks: ShipRunHo
`Run: ${runId}`,
"Workflow: ship",
`Status: ${finalRunRecord.status}`,
`Execution policy: ${policy.safe ? "dangerous default disabled via --safe" : "default dangerous execution"}`,
`Execution policy: ${policy.safe ? "safe overrides applied via --safe" : "default execution policy"}`,
`Ship readiness: ${execution.shipRecord.readiness}`,
`GitHub mutation: ${execution.githubMutationRecord.summary}`,
`GitHub delivery: ${execution.githubDeliveryRecord.overall.status}`,
Expand Down
8 changes: 4 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { ConfigProvenance, ConfigValueSource, CstackConfig } from "./types.
const DEFAULT_CONFIG: CstackConfig = {
codex: {
command: process.env.CSTACK_CODEX_BIN || "codex",
sandbox: "danger-full-access",
sandbox: "workspace-write",
extraArgs: []
},
workflows: {
Expand Down Expand Up @@ -40,7 +40,7 @@ const DEFAULT_CONFIG: CstackConfig = {
build: {
mode: "interactive",
verificationCommands: [],
allowDirty: true,
allowDirty: false,
maxCodexAttempts: 3,
timeoutSeconds: 900,
capabilities: {
Expand Down Expand Up @@ -69,7 +69,7 @@ const DEFAULT_CONFIG: CstackConfig = {
ship: {
mode: "exec",
verificationCommands: [],
allowDirty: true,
allowDirty: false,
timeoutSeconds: 600,
capabilities: {
allowed: ["shell", "github"],
Expand All @@ -83,7 +83,7 @@ const DEFAULT_CONFIG: CstackConfig = {
deliver: {
mode: "interactive",
verificationCommands: [],
allowDirty: true,
allowDirty: false,
timeoutSeconds: 900,
capabilities: {
allowed: ["shell", "github", "browser"],
Expand Down
2 changes: 1 addition & 1 deletion src/inspector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,7 @@ export function renderInspectionSummary(cwd: string, inspection: RunInspection):
? `- source snapshot: ${inspection.executionContext.source.branch} ${inspection.executionContext.source.commit}`
: undefined,
inspection.executionContext
? `- execution policy: ${run.inputs.safe ? "dangerous default disabled via --safe" : "default dangerous execution"}`
? `- execution policy: ${run.inputs.safe ? "safe overrides applied via --safe" : "default execution policy"}`
: undefined,
inspection.executionContext?.source.localChangesIgnored
? "- local dirty changes: ignored by default; execution used committed HEAD"
Expand Down
4 changes: 2 additions & 2 deletions src/runtime-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ export function resolveSourceExecutionReason(options: {
if (options.configuredAllowDirtySource && options.configuredAllowDirtySource !== "default") {
return `Direct source execution was enabled by configured allowDirty for ${options.workflow}.`;
}
return `Direct source execution used the default dangerous execution policy for ${options.workflow}.`;
return `Direct source execution used the default execution policy for ${options.workflow}.`;
}

export function emitDeprecatedAllowAllWarning(command: string): void {
process.stderr.write(
`[cstack] Warning: \`--allow-all\` is deprecated for \`${command}\` and has no effect because dangerous execution is now the default.\n`
`[cstack] Warning: \`--allow-all\` is deprecated for \`${command}\` and has no effect.\n`
);
}
15 changes: 7 additions & 8 deletions test/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ describe("runBuild", () => {
expect(await fs.readFile(path.join(executionContext.execution.cwd, "codex-generated-change.txt"), "utf8")).toContain("generated");
}, 60_000);

it("uses the source checkout and danger-full-access by default when sandbox and allowDirty are not configured", async () => {
it("uses an isolated checkout and workspace-write by default when sandbox and allowDirty are not configured", async () => {
await fs.writeFile(path.join(repoDir, "local-only.txt"), "uncommitted\n", "utf8");
const configPath = path.join(repoDir, ".cstack", "config.toml");
await fs.writeFile(
Expand Down Expand Up @@ -322,15 +322,14 @@ describe("runBuild", () => {
codexCommand: string[];
};

expect(run.inputs.allowDirty).toBe(true);
expect(run.inputs.allowDirty).toBe(false);
expect(executionContext.source.dirtyFiles).toContain("local-only.txt");
expect(executionContext.source.localChangesIgnored).toBe(false);
expect(executionContext.execution.kind).toBe("source");
expect(executionContext.execution.cwd).toBe(repoDir);
expect(executionContext.execution.notes.join(" ")).toContain("default dangerous execution policy");
expect(executionContext.source.localChangesIgnored).toBe(true);
expect(executionContext.execution.kind).toBe("git-worktree");
expect(executionContext.execution.cwd).not.toBe(repoDir);
expect(session.codexCommand).toContain("--sandbox");
expect(session.codexCommand).toContain("danger-full-access");
expect(await fs.readFile(path.join(repoDir, "codex-generated-change.txt"), "utf8")).toContain("generated");
expect(session.codexCommand).toContain("workspace-write");
await expect(fs.access(path.join(repoDir, "codex-generated-change.txt"))).rejects.toThrow();
}, 60_000);

it("treats --allow-all as a deprecated no-op", async () => {
Expand Down
8 changes: 4 additions & 4 deletions test/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,18 @@ blockSeverities = ["medium", "high", "critical"]
const { config, sources, provenance } = await loadConfig(repoDir);

expect(sources).toHaveLength(0);
expect(config.codex.sandbox).toBe("danger-full-access");
expect(config.codex.sandbox).toBe("workspace-write");
expect(config.workflows.spec.timeoutSeconds).toBe(600);
expect(config.workflows.discover.timeoutSeconds).toBe(600);
expect(config.workflows.build.allowDirty).toBe(true);
expect(config.workflows.build.allowDirty).toBe(false);
expect(config.workflows.build.timeoutSeconds).toBe(900);
expect(config.workflows.review.mode).toBe("exec");
expect(config.workflows.review.allowDirty).toBe(true);
expect(config.workflows.review.timeoutSeconds).toBe(600);
expect(config.workflows.ship.mode).toBe("exec");
expect(config.workflows.ship.allowDirty).toBe(true);
expect(config.workflows.ship.allowDirty).toBe(false);
expect(config.workflows.ship.timeoutSeconds).toBe(600);
expect(config.workflows.deliver.allowDirty).toBe(true);
expect(config.workflows.deliver.allowDirty).toBe(false);
expect(config.workflows.deliver.timeoutSeconds).toBe(900);
expect(config.workflows.deliver.stageTimeoutSeconds?.build).toBe(900);
expect(config.workflows.deliver.stageTimeoutSeconds?.validation).toBe(600);
Expand Down
15 changes: 7 additions & 8 deletions test/deliver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ describe("runDeliver", () => {
expect(lineage.stages.find((stage) => stage.name === "validation")?.status).toBe("deferred");
}, 60_000);

it("uses the source checkout and danger-full-access by default when sandbox and allowDirty are not configured", async () => {
it("uses an isolated checkout and workspace-write by default when sandbox and allowDirty are not configured", async () => {
const configPath = path.join(repoDir, ".cstack", "config.toml");
const configBody = await fs.readFile(configPath, "utf8");
await fs.writeFile(
Expand Down Expand Up @@ -451,15 +451,14 @@ describe("runDeliver", () => {
codexCommand: string[];
};

expect(run.inputs.allowDirty).toBe(true);
expect(run.inputs.allowDirty).toBe(false);
expect(executionContext.source.dirtyFiles).toContain("src-change.txt");
expect(executionContext.source.localChangesIgnored).toBe(false);
expect(executionContext.execution.kind).toBe("source");
expect(executionContext.execution.cwd).toBe(repoDir);
expect(executionContext.execution.notes.join(" ")).toContain("default dangerous execution policy");
expect(executionContext.source.localChangesIgnored).toBe(true);
expect(executionContext.execution.kind).toBe("git-worktree");
expect(executionContext.execution.cwd).not.toBe(repoDir);
expect(buildSession.codexCommand).toContain("--sandbox");
expect(buildSession.codexCommand).toContain("danger-full-access");
expect(await fs.readFile(path.join(repoDir, "codex-generated-change.txt"), "utf8")).toContain("generated");
expect(buildSession.codexCommand).toContain("workspace-write");
await expect(fs.access(path.join(repoDir, "codex-generated-change.txt"))).rejects.toThrow();
}, 60_000);

it("treats --allow-all as a deprecated no-op when source execution is otherwise disabled", async () => {
Expand Down
Loading