@valescoagency/runway 0.14.0 → 0.14.1
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/README.md
CHANGED
|
@@ -541,7 +541,7 @@ These are tractable, just not v1.
|
|
|
541
541
|
|
|
542
542
|
## Status
|
|
543
543
|
|
|
544
|
-
0.14.
|
|
544
|
+
0.14.1 — production-shaped and dogfooded against live Linear queues.
|
|
545
545
|
The end-to-end pipeline (init → run → review → PR) is stable; surface
|
|
546
546
|
may still shift as the orchestrator's policy and iteration mechanics
|
|
547
547
|
mature. See [CHANGELOG.md](./CHANGELOG.md) for per-release detail.
|
package/dist/repo-upgrade.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { AUTH_MODE_ENV_VAR, TEMPLATES_DIR, } from "./scaffolder.js";
|
|
4
4
|
import { buildAgentImage } from "./scaffolder-image.js";
|
|
@@ -80,7 +80,36 @@ export function parseOpRefs(schema, opts) {
|
|
|
80
80
|
// ---------------------------------------------------------------------------
|
|
81
81
|
// Render: Dockerfile
|
|
82
82
|
// ---------------------------------------------------------------------------
|
|
83
|
-
|
|
83
|
+
/**
|
|
84
|
+
* VA-466: read every historical snapshot under `templates/history/`
|
|
85
|
+
* that matches the base Dockerfile naming pattern, flatten them to
|
|
86
|
+
* the set of lines that have ever shipped as canonical content.
|
|
87
|
+
*
|
|
88
|
+
* Files are named `Dockerfile.claude-code.base.v<n>` (where `<n>` is
|
|
89
|
+
* the runway version that owned that exact content). The detector
|
|
90
|
+
* doesn't care about version ordering — it just needs the union of
|
|
91
|
+
* lines so a target Dockerfile rendered at any prior version doesn't
|
|
92
|
+
* trigger false-positive "manual edit" reports.
|
|
93
|
+
*
|
|
94
|
+
* Missing or empty `history/` directory returns an empty list — both
|
|
95
|
+
* are valid states (a fresh checkout that hasn't accumulated history
|
|
96
|
+
* yet, or a tier-1 repo whose template never changed).
|
|
97
|
+
*/
|
|
98
|
+
function historicalBaseTemplateLines() {
|
|
99
|
+
const historyDir = join(TEMPLATES_DIR, "history");
|
|
100
|
+
if (!existsSync(historyDir))
|
|
101
|
+
return [];
|
|
102
|
+
const out = [];
|
|
103
|
+
for (const name of readdirSync(historyDir)) {
|
|
104
|
+
if (!name.startsWith("Dockerfile.claude-code.base"))
|
|
105
|
+
continue;
|
|
106
|
+
const contents = readFileSync(join(historyDir, name), "utf8");
|
|
107
|
+
for (const line of contents.split("\n"))
|
|
108
|
+
out.push(line);
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
export function renderDockerfile(cwd, tier, opts, enforceManualEditGuard) {
|
|
84
113
|
const dockerfilePath = join(cwd, ".sandcastle", "Dockerfile");
|
|
85
114
|
const before = readFileSync(dockerfilePath, "utf8");
|
|
86
115
|
const base = readFileSync(join(TEMPLATES_DIR, "Dockerfile.claude-code.base"), "utf8");
|
|
@@ -98,8 +127,22 @@ function renderDockerfile(cwd, tier, opts, enforceManualEditGuard) {
|
|
|
98
127
|
}
|
|
99
128
|
// Detect manual user edits: any line in `before` that isn't in the
|
|
100
129
|
// expected re-rendered output is foreign. Warn loudly unless --force.
|
|
130
|
+
//
|
|
131
|
+
// VA-466: expectedLines unions the current template with every
|
|
132
|
+
// historical canonical template snapshot under `templates/history/`.
|
|
133
|
+
// Without this, a target repo's Dockerfile rendered by an older
|
|
134
|
+
// runway version flags every cross-version line delta as a "manual
|
|
135
|
+
// edit" — false-positive that forces operators to pass `--force`
|
|
136
|
+
// and lose the detector's real signal. Each release that mutates
|
|
137
|
+
// `Dockerfile.claude-code.base` snapshots the prior version into
|
|
138
|
+
// `templates/history/Dockerfile.claude-code.base.v<n>` BEFORE the
|
|
139
|
+
// edit lands; the detector unions all of them so any line that
|
|
140
|
+
// ever shipped as canonical stays trusted.
|
|
101
141
|
if (before !== after && !opts.force && enforceManualEditGuard) {
|
|
102
142
|
const expectedLines = new Set(after.split("\n"));
|
|
143
|
+
for (const line of historicalBaseTemplateLines()) {
|
|
144
|
+
expectedLines.add(line);
|
|
145
|
+
}
|
|
103
146
|
const foreign = before
|
|
104
147
|
.split("\n")
|
|
105
148
|
.filter((l) => l.trim().length && !expectedLines.has(l));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valescoagency/runway",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Linear-driven orchestrator + scaffolder for coding agents on Sandcastle. `runway init` scaffolds a target repo (sandcastle + varlock + 1Password); `runway run` drains a Linear queue against it; `runway doctor`, `runway upgrade`, `runway upgrade-repo` round out the lifecycle.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Canonical claude-code Dockerfile — vendored from
|
|
2
|
+
# @ai-hero/sandcastle's InitService.ts (CLAUDE_CODE_DOCKERFILE constant).
|
|
3
|
+
# Kept here so `runway init` can write it directly, without invoking
|
|
4
|
+
# `sandcastle init` (which has interactive prompts that hang in
|
|
5
|
+
# non-TTY environments like CI / Mac Mini cron).
|
|
6
|
+
#
|
|
7
|
+
# Drift policy: when sandcastle bumps its claude-code Dockerfile,
|
|
8
|
+
# refresh this file. The diff should be tiny — runway's tier 2 layer
|
|
9
|
+
# patches AFTER this base, so adopters re-run `runway init --force`
|
|
10
|
+
# to roll forward.
|
|
11
|
+
|
|
12
|
+
FROM node:24-bookworm
|
|
13
|
+
|
|
14
|
+
# Install system dependencies
|
|
15
|
+
RUN apt-get update && apt-get install -y \
|
|
16
|
+
git \
|
|
17
|
+
curl \
|
|
18
|
+
jq \
|
|
19
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
20
|
+
|
|
21
|
+
# Build-args for UID/GID alignment: defaults match the host user's
|
|
22
|
+
# UID/GID at build time so image-built files and bind-mounted files
|
|
23
|
+
# share an owner without runtime chown.
|
|
24
|
+
ARG AGENT_UID=1000
|
|
25
|
+
ARG AGENT_GID=1000
|
|
26
|
+
|
|
27
|
+
# Rename the base image's "node" user to "agent" and align UID/GID.
|
|
28
|
+
#
|
|
29
|
+
# Divergence from sandcastle's stock Dockerfile: stock runs
|
|
30
|
+
# `groupmod -g $AGENT_GID node` unconditionally, which fails on macOS
|
|
31
|
+
# hosts where the host GID is 20 (`staff`) — Debian's `dialout` group
|
|
32
|
+
# already has GID 20, and `groupmod` refuses to assign a duplicate
|
|
33
|
+
# GID. We guard with `getent group` so groupmod only runs if the
|
|
34
|
+
# target GID is unused; if it's already taken, we point the agent
|
|
35
|
+
# user at the pre-existing group via `usermod -g <gid>` and the
|
|
36
|
+
# image still works (the in-image group name is irrelevant — only the
|
|
37
|
+
# numeric GID matters for bind-mount permissions).
|
|
38
|
+
RUN if ! getent group $AGENT_GID >/dev/null; then \
|
|
39
|
+
groupmod -g $AGENT_GID node; \
|
|
40
|
+
fi \
|
|
41
|
+
&& usermod -u $AGENT_UID -g $AGENT_GID -d /home/agent -m -l agent node
|
|
42
|
+
|
|
43
|
+
# VA-351: bake the container env up front so agents don't manually
|
|
44
|
+
# work around host-path leaks, missing pnpm, or unset HOME on every
|
|
45
|
+
# iteration. Without these, every agent run repeats the same
|
|
46
|
+
# corepack/TURBO_CACHE_DIR/HOME setup commands — see VA-312's run log
|
|
47
|
+
# for the receipts.
|
|
48
|
+
ENV HOME=/home/agent
|
|
49
|
+
ENV XDG_CACHE_HOME=/home/agent/.cache
|
|
50
|
+
ENV TURBO_CACHE_DIR=/tmp/turbo-cache
|
|
51
|
+
ENV pnpm_config_cache=/home/agent/.cache/pnpm
|
|
52
|
+
|
|
53
|
+
# Pre-create cache dirs with agent ownership so the first pnpm/turbo
|
|
54
|
+
# run doesn't have to chown them. Both are inside paths the agent owns
|
|
55
|
+
# anyway; this just makes them exist.
|
|
56
|
+
RUN mkdir -p /home/agent/.cache /home/agent/.cache/pnpm /tmp/turbo-cache \
|
|
57
|
+
&& chown -R $AGENT_UID:$AGENT_GID /home/agent/.cache /tmp/turbo-cache
|
|
58
|
+
|
|
59
|
+
# Bake pnpm via corepack at build time so `pnpm` is on PATH inside the
|
|
60
|
+
# container before any agent command runs. Pin a default; target repos
|
|
61
|
+
# can override at runtime via `packageManager` in package.json +
|
|
62
|
+
# `corepack use`.
|
|
63
|
+
RUN corepack enable \
|
|
64
|
+
&& corepack prepare pnpm@11.1.1 --activate
|
|
65
|
+
|
|
66
|
+
USER ${AGENT_UID}:${AGENT_GID}
|
|
67
|
+
|
|
68
|
+
# Install Claude Code CLI
|
|
69
|
+
RUN curl -fsSL https://claude.ai/install.sh | bash
|
|
70
|
+
|
|
71
|
+
# Add Claude to PATH
|
|
72
|
+
ENV PATH="/home/agent/.local/bin:$PATH"
|
|
73
|
+
|
|
74
|
+
WORKDIR /home/agent
|
|
75
|
+
|
|
76
|
+
# In worktree sandbox mode, Sandcastle bind-mounts the git worktree at
|
|
77
|
+
# the sandbox repo dir and overrides the working directory to that dir
|
|
78
|
+
# at container start.
|
|
79
|
+
ENTRYPOINT ["sleep", "infinity"]
|