@plainconceptsplatform/workflows 0.17.0 → 0.20.0
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/dist/catalog-installation.js +25 -13
- package/dist/stack-defaults.js +16 -16
- package/dist/worker-env.js +24 -21
- package/loops/actions/add-issue-labels/action.yml +50 -50
- package/loops/actions/agent-output.cjs +17 -17
- package/loops/actions/apply-agent-bundle/action.yml +24 -24
- package/loops/actions/apply-agent-comments/action.yml +42 -42
- package/loops/actions/apply-agent-labels/action.yml +55 -55
- package/loops/actions/apply-agent-output/action.yml +108 -108
- package/loops/actions/assess-blast-radius/action.yml +148 -0
- package/loops/actions/assess-blast-radius/assess-blast-radius.sh +138 -0
- package/loops/actions/classify-route/action.yml +100 -100
- package/loops/actions/cleanup-artifacts/action.yml +91 -91
- package/loops/actions/close-agent-issues/action.yml +43 -43
- package/loops/actions/create-agent-issues/action.yml +52 -52
- package/loops/actions/create-issue-comment/action.yml +29 -29
- package/loops/actions/download-agent-output/action.yml +53 -53
- package/loops/actions/housekeeping/action.yml +55 -2
- package/loops/actions/identify-gate-subject/action.yml +134 -122
- package/loops/actions/link-pr-to-issue/action.yml +40 -40
- package/loops/actions/list-open-issues/action.yml +33 -33
- package/loops/actions/load-issue-context/action.yml +45 -45
- package/loops/actions/merge-agent-pr/action.yml +49 -49
- package/loops/actions/push-agent-branch/action.yml +45 -45
- package/loops/actions/remove-issue-labels/action.yml +37 -37
- package/loops/actions/require-open-issue/action.yml +59 -0
- package/loops/actions/update-agent-issues/action.yml +58 -58
- package/loops/actions/validate-merge-gate-output/action.yml +62 -40
- package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +147 -31
- package/loops/actions/validate-refine-output/action.yml +48 -44
- package/loops/actions/validate-refine-output/validate-refine-output.sh +15 -4
- package/loops/actions/validate-review-output/action.yml +35 -35
- package/loops/actions/validate-triage-output/action.yml +36 -36
- package/loops/actions/verify-composite-actions/action.yml +9 -9
- package/loops/actions/verify-refine-output/action.yml +9 -9
- package/loops/actions/verify-refine-output/verify-refine-output.sh +6 -1
- package/loops/actions/verify-route-matrix/action.yml +9 -9
- package/loops/actions/verify-route-matrix/verify-gate-metrics.mjs +51 -0
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +630 -8
- package/loops/scripts/compile-agent-workflows.mjs +331 -331
- package/loops/templates/agentics/agentics-maintenance.yml +121 -121
- package/loops/templates/ci/app-ci-dotnet-next.yml +330 -330
- package/loops/templates/ci/app-ci-node-monorepo.yml +260 -260
- package/loops/templates/issues/bug_report.yml +109 -109
- package/loops/templates/issues/feature_request.yml +75 -75
- package/loops/templates/opencode/opencode.ci.json +55 -49
- package/loops/templates/opencode/opencode.ci.json.md +59 -49
- package/loops/templates/release/github-release.yml +30 -30
- package/loops/workflows/agent-apply-review.md +33 -3
- package/loops/workflows/agent-audit.md +36 -0
- package/loops/workflows/agent-implement.md +77 -5
- package/loops/workflows/agent-merge-gate.md +368 -148
- package/loops/workflows/agent-refine.md +93 -17
- package/loops/workflows/agent-release.md +4 -4
- package/loops/workflows/agent-triage.md +33 -1
- package/loops/workflows/authorize-bot-work.yml +105 -105
- package/loops/workflows/shared/opencode-ci.md +206 -206
- package/loops/workflows/shared/platform-defaults.md +19 -19
- package/loops/workflows/work-router.yml +25 -11
- package/package.json +2 -2
|
@@ -1,206 +1,206 @@
|
|
|
1
|
-
---
|
|
2
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/shared/opencode-ci.md. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
3
|
-
env:
|
|
4
|
-
AGENTMEMORY_VERSION: "0.9.28"
|
|
5
|
-
CODEGRAPH_VERSION: "1.6.0"
|
|
6
|
-
RTK_VERSION: "0.44.1"
|
|
7
|
-
RTK_SHA256: "986f29704469b3d1051e2474105c6c75ab8b73651068dcd61612c1fb3938ad95"
|
|
8
|
-
description: |
|
|
9
|
-
Shared CI setup for Platform agent workflows. Installs pinned tooling and merges
|
|
10
|
-
opencode.ci.json into opencode.jsonc so the CI agent gets its provider and model config.
|
|
11
|
-
|
|
12
|
-
Consumer-specific steps (NuGet, .NET restore, OpenSpec, etc.) should be added after the
|
|
13
|
-
shared baseline in the consumer copy. The merge step below is package-owned and required
|
|
14
|
-
for the agent to resolve its provider and its models.
|
|
15
|
-
|
|
16
|
-
# Consumer repositories should add stack-specific steps (NuGet cache, dotnet restore,
|
|
17
|
-
# OpenSpec, Playwright, etc.) after the shared baseline. The merge step at the end is
|
|
18
|
-
# package-owned and required for the agent to resolve its provider and models. Do not
|
|
19
|
-
# remove it.
|
|
20
|
-
pre-agent-steps:
|
|
21
|
-
- name: Create agent scratch directory
|
|
22
|
-
run: mkdir -p .opencode/.tmp
|
|
23
|
-
|
|
24
|
-
- name: Install the Docker Compose plugin
|
|
25
|
-
# The ARC runner image ships the docker CLI without the compose plugin, and awf drives its
|
|
26
|
-
# sandbox with `docker compose up`. User-space install; no root required.
|
|
27
|
-
run: |
|
|
28
|
-
set -euo pipefail
|
|
29
|
-
if docker compose version >/dev/null 2>&1; then
|
|
30
|
-
echo "compose already present"; exit 0
|
|
31
|
-
fi
|
|
32
|
-
mkdir -p "$HOME/.docker/cli-plugins"
|
|
33
|
-
curl -sSfL "https://github.com/docker/compose/releases/download/v2.39.2/docker-compose-linux-x86_64" -o "$HOME/.docker/cli-plugins/docker-compose"
|
|
34
|
-
chmod +x "$HOME/.docker/cli-plugins/docker-compose"
|
|
35
|
-
docker compose version
|
|
36
|
-
|
|
37
|
-
- name: Install ripgrep
|
|
38
|
-
run: |
|
|
39
|
-
set -euo pipefail
|
|
40
|
-
|
|
41
|
-
if command -v rg > /dev/null 2>&1; then
|
|
42
|
-
echo "ripgrep already installed: $(rg --version | head -1)"
|
|
43
|
-
exit 0
|
|
44
|
-
fi
|
|
45
|
-
|
|
46
|
-
# ARC runner pods have no root, so ripgrep comes from its release tarball into a
|
|
47
|
-
# user-writable prefix instead of apt.
|
|
48
|
-
mkdir -p "$HOME/.local/bin"
|
|
49
|
-
curl -sSfL https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz | tar -xz --strip-components=1 -C "$HOME/.local/bin" --wildcards "*/rg"
|
|
50
|
-
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
51
|
-
rg --version
|
|
52
|
-
|
|
53
|
-
- name: Activate the pnpm version package.json pins
|
|
54
|
-
run: |
|
|
55
|
-
set -euo pipefail
|
|
56
|
-
corepack enable
|
|
57
|
-
corepack prepare --activate
|
|
58
|
-
pnpm --version
|
|
59
|
-
|
|
60
|
-
- name: Cache the pnpm store
|
|
61
|
-
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
62
|
-
with:
|
|
63
|
-
path: ~/.local/share/pnpm/store
|
|
64
|
-
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
|
65
|
-
restore-keys: pnpm-store-${{ runner.os }}-
|
|
66
|
-
|
|
67
|
-
- name: Install RTK
|
|
68
|
-
run: |
|
|
69
|
-
set -euo pipefail
|
|
70
|
-
|
|
71
|
-
if command -v rtk > /dev/null 2>&1 && rtk --version 2>/dev/null | grep -q "${RTK_VERSION}"; then
|
|
72
|
-
echo "RTK ${RTK_VERSION} already installed"
|
|
73
|
-
exit 0
|
|
74
|
-
fi
|
|
75
|
-
|
|
76
|
-
tarball="$RUNNER_TEMP/rtk.tar.gz"
|
|
77
|
-
curl -fsSL -o "$tarball" \
|
|
78
|
-
"https://github.com/rtk-ai/rtk/releases/download/v${RTK_VERSION}/rtk-x86_64-unknown-linux-musl.tar.gz"
|
|
79
|
-
echo "${RTK_SHA256} $tarball" | sha256sum --check --strict
|
|
80
|
-
|
|
81
|
-
tar -xzf "$tarball" -C "$RUNNER_TEMP"
|
|
82
|
-
mkdir -p "$HOME/.local/bin"
|
|
83
|
-
install -m 0755 "$RUNNER_TEMP/rtk" "$HOME/.local/bin/rtk"
|
|
84
|
-
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
85
|
-
|
|
86
|
-
rtk --version
|
|
87
|
-
rtk init -g --opencode --auto-patch
|
|
88
|
-
|
|
89
|
-
- name: Install agentmemory
|
|
90
|
-
run: |
|
|
91
|
-
set -euo pipefail
|
|
92
|
-
|
|
93
|
-
if command -v agentmemory > /dev/null 2>&1 && agentmemory --version 2>/dev/null | grep -q "${AGENTMEMORY_VERSION}"; then
|
|
94
|
-
echo "agentmemory ${AGENTMEMORY_VERSION} already installed"
|
|
95
|
-
exit 0
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
npm install -g "@agentmemory/agentmemory@${AGENTMEMORY_VERSION}"
|
|
99
|
-
agentmemory --version
|
|
100
|
-
|
|
101
|
-
- name: Restore the CodeGraph index
|
|
102
|
-
# Ephemeral ARC runners start empty, so without this every run rebuilds the whole graph.
|
|
103
|
-
# actions/cache is repository-scoped by design, which keeps consumers isolated, and
|
|
104
|
-
# each run saves an immutable snapshot under its own key at job end (the action's built-in
|
|
105
|
-
# post step), so two concurrent runs never write the same entry: the newest snapshot simply
|
|
106
|
-
# wins the next restore. The index lives in .codegraph inside the checkout plus a small
|
|
107
|
-
# registry in ~/.codegraph.
|
|
108
|
-
uses: actions/cache@v4
|
|
109
|
-
with:
|
|
110
|
-
path: |
|
|
111
|
-
.codegraph
|
|
112
|
-
~/.codegraph
|
|
113
|
-
key: codegraph-${{ github.repository_id }}-${{ github.run_id }}
|
|
114
|
-
restore-keys: |
|
|
115
|
-
codegraph-${{ github.repository_id }}-
|
|
116
|
-
|
|
117
|
-
- name: Install codegraph and index the repository
|
|
118
|
-
continue-on-error: true
|
|
119
|
-
run: |
|
|
120
|
-
set -euo pipefail
|
|
121
|
-
|
|
122
|
-
if command -v codegraph > /dev/null 2>&1 && codegraph --version 2>/dev/null | grep -q "${CODEGRAPH_VERSION}"; then
|
|
123
|
-
echo "codegraph ${CODEGRAPH_VERSION} already installed"
|
|
124
|
-
else
|
|
125
|
-
npm install -g "@colbymchenry/codegraph@${CODEGRAPH_VERSION}"
|
|
126
|
-
fi
|
|
127
|
-
|
|
128
|
-
codegraph init
|
|
129
|
-
|
|
130
|
-
- name: Install OpenSpec CLI
|
|
131
|
-
run: |
|
|
132
|
-
set -euo pipefail
|
|
133
|
-
|
|
134
|
-
if command -v openspec > /dev/null 2>&1 && openspec --version 2>/dev/null | grep -q "1.8.0"; then
|
|
135
|
-
echo "openspec 1.8.0 already installed"
|
|
136
|
-
exit 0
|
|
137
|
-
fi
|
|
138
|
-
|
|
139
|
-
npm install -g "@fission-ai/openspec@1.8.0"
|
|
140
|
-
openspec --version
|
|
141
|
-
|
|
142
|
-
# NOTE: playwright-cli and SQL Server startup steps are not part of the shared CI
|
|
143
|
-
# baseline. The agent path captures no visual evidence: it cannot reach a browser
|
|
144
|
-
# from inside the awf sandbox, and a screenshot with no baseline to compare against
|
|
145
|
-
# gated nothing. Run /ops-evidence locally when a change warrants screenshots. If
|
|
146
|
-
# you need playwright-cli or SQL Server inside the agent sandbox for other reasons,
|
|
147
|
-
# add them as consumer-specific steps after the shared baseline.
|
|
148
|
-
|
|
149
|
-
- name: Setup .NET
|
|
150
|
-
# Ephemeral VMs carry no SDK; the old host had it baked in, and GitHub-hosted images made
|
|
151
|
-
# the dependency invisible. setup-dotnet caches per run from the MS CDN.
|
|
152
|
-
uses: actions/setup-dotnet@v5
|
|
153
|
-
with:
|
|
154
|
-
dotnet-version: 10.0.x
|
|
155
|
-
env:
|
|
156
|
-
# the default /usr/share/dotnet needs root; the tool cache belongs to the runner user
|
|
157
|
-
DOTNET_INSTALL_DIR: ${{ runner.tool_cache }}/dotnet
|
|
158
|
-
|
|
159
|
-
- name: Cache NuGet packages
|
|
160
|
-
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
161
|
-
with:
|
|
162
|
-
path: ~/.nuget/packages
|
|
163
|
-
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.slnx', '**/Directory.Packages.props') }}
|
|
164
|
-
restore-keys: nuget-${{ runner.os }}-
|
|
165
|
-
|
|
166
|
-
- name: Install workspace dependencies
|
|
167
|
-
run: pnpm install --frozen-lockfile
|
|
168
|
-
|
|
169
|
-
- name: Merge the CI-only OpenCode provider into opencode.jsonc
|
|
170
|
-
run: |
|
|
171
|
-
set -euo pipefail
|
|
172
|
-
|
|
173
|
-
CONFIG=opencode.jsonc
|
|
174
|
-
FRAGMENT=opencode.ci.json
|
|
175
|
-
|
|
176
|
-
[ -f "$FRAGMENT" ] || { echo "::error::$FRAGMENT is missing from the checkout"; exit 1; }
|
|
177
|
-
|
|
178
|
-
# Pure JSON on purpose, not JSONC: jq cannot parse `//` comments, and a naive
|
|
179
|
-
# comment-stripper would corrupt the `http://` inside the provider's api URL.
|
|
180
|
-
jq -e . "$FRAGMENT" > /dev/null \
|
|
181
|
-
|| { echo "::error::$FRAGMENT is not valid JSON. Comments are not allowed in it."; exit 1; }
|
|
182
|
-
|
|
183
|
-
# Despite the .jsonc name, this file is committed in this repository and is read by
|
|
184
|
-
# jq below, so it must contain no comments. A single `//` line fails the merge with
|
|
185
|
-
# "Invalid numeric literal", which names neither the file nor the reason.
|
|
186
|
-
if [ -f "$CONFIG" ] && ! jq -e . "$CONFIG" > /dev/null 2>&1; then
|
|
187
|
-
echo "::error::$CONFIG is tracked and must be comment-free JSON: jq cannot parse it."
|
|
188
|
-
exit 1
|
|
189
|
-
fi
|
|
190
|
-
|
|
191
|
-
# opencode.jsonc is untracked in most repositories, so it usually does not exist here.
|
|
192
|
-
# Create it from the fragment when absent, merge when a checkout did provide one.
|
|
193
|
-
if [ -f "$CONFIG" ]; then
|
|
194
|
-
merged=$(jq -s '.[0] * .[1]' "$CONFIG" "$FRAGMENT")
|
|
195
|
-
else
|
|
196
|
-
merged=$(jq -S . "$FRAGMENT")
|
|
197
|
-
fi
|
|
198
|
-
|
|
199
|
-
printf '%s\n' "$merged" > "$CONFIG"
|
|
200
|
-
|
|
201
|
-
# gh-aw's own "Write OpenCode Config" step runs next and merges its base config with
|
|
202
|
-
# `$existing * $base`. Base wins on conflicting keys, but it defines neither `model`
|
|
203
|
-
# nor this provider, so both survive and `awf-proxy` is added alongside.
|
|
204
|
-
echo "Wrote $CONFIG from $FRAGMENT:"
|
|
205
|
-
jq -r '" model: \(.model // "unset")", " plugins: \(.plugin // [] | join(", "))", " providers: \(.provider // {} | keys | join(", "))"' "$CONFIG"
|
|
206
|
-
---
|
|
1
|
+
---
|
|
2
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/shared/opencode-ci.md. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
3
|
+
env:
|
|
4
|
+
AGENTMEMORY_VERSION: "0.9.28"
|
|
5
|
+
CODEGRAPH_VERSION: "1.6.0"
|
|
6
|
+
RTK_VERSION: "0.44.1"
|
|
7
|
+
RTK_SHA256: "986f29704469b3d1051e2474105c6c75ab8b73651068dcd61612c1fb3938ad95"
|
|
8
|
+
description: |
|
|
9
|
+
Shared CI setup for Platform agent workflows. Installs pinned tooling and merges
|
|
10
|
+
opencode.ci.json into opencode.jsonc so the CI agent gets its provider and model config.
|
|
11
|
+
|
|
12
|
+
Consumer-specific steps (NuGet, .NET restore, OpenSpec, etc.) should be added after the
|
|
13
|
+
shared baseline in the consumer copy. The merge step below is package-owned and required
|
|
14
|
+
for the agent to resolve its provider and its models.
|
|
15
|
+
|
|
16
|
+
# Consumer repositories should add stack-specific steps (NuGet cache, dotnet restore,
|
|
17
|
+
# OpenSpec, Playwright, etc.) after the shared baseline. The merge step at the end is
|
|
18
|
+
# package-owned and required for the agent to resolve its provider and models. Do not
|
|
19
|
+
# remove it.
|
|
20
|
+
pre-agent-steps:
|
|
21
|
+
- name: Create agent scratch directory
|
|
22
|
+
run: mkdir -p .opencode/.tmp
|
|
23
|
+
|
|
24
|
+
- name: Install the Docker Compose plugin
|
|
25
|
+
# The ARC runner image ships the docker CLI without the compose plugin, and awf drives its
|
|
26
|
+
# sandbox with `docker compose up`. User-space install; no root required.
|
|
27
|
+
run: |
|
|
28
|
+
set -euo pipefail
|
|
29
|
+
if docker compose version >/dev/null 2>&1; then
|
|
30
|
+
echo "compose already present"; exit 0
|
|
31
|
+
fi
|
|
32
|
+
mkdir -p "$HOME/.docker/cli-plugins"
|
|
33
|
+
curl -sSfL "https://github.com/docker/compose/releases/download/v2.39.2/docker-compose-linux-x86_64" -o "$HOME/.docker/cli-plugins/docker-compose"
|
|
34
|
+
chmod +x "$HOME/.docker/cli-plugins/docker-compose"
|
|
35
|
+
docker compose version
|
|
36
|
+
|
|
37
|
+
- name: Install ripgrep
|
|
38
|
+
run: |
|
|
39
|
+
set -euo pipefail
|
|
40
|
+
|
|
41
|
+
if command -v rg > /dev/null 2>&1; then
|
|
42
|
+
echo "ripgrep already installed: $(rg --version | head -1)"
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# ARC runner pods have no root, so ripgrep comes from its release tarball into a
|
|
47
|
+
# user-writable prefix instead of apt.
|
|
48
|
+
mkdir -p "$HOME/.local/bin"
|
|
49
|
+
curl -sSfL https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz | tar -xz --strip-components=1 -C "$HOME/.local/bin" --wildcards "*/rg"
|
|
50
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
51
|
+
rg --version
|
|
52
|
+
|
|
53
|
+
- name: Activate the pnpm version package.json pins
|
|
54
|
+
run: |
|
|
55
|
+
set -euo pipefail
|
|
56
|
+
corepack enable
|
|
57
|
+
corepack prepare --activate
|
|
58
|
+
pnpm --version
|
|
59
|
+
|
|
60
|
+
- name: Cache the pnpm store
|
|
61
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
62
|
+
with:
|
|
63
|
+
path: ~/.local/share/pnpm/store
|
|
64
|
+
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
|
65
|
+
restore-keys: pnpm-store-${{ runner.os }}-
|
|
66
|
+
|
|
67
|
+
- name: Install RTK
|
|
68
|
+
run: |
|
|
69
|
+
set -euo pipefail
|
|
70
|
+
|
|
71
|
+
if command -v rtk > /dev/null 2>&1 && rtk --version 2>/dev/null | grep -q "${RTK_VERSION}"; then
|
|
72
|
+
echo "RTK ${RTK_VERSION} already installed"
|
|
73
|
+
exit 0
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
tarball="$RUNNER_TEMP/rtk.tar.gz"
|
|
77
|
+
curl -fsSL -o "$tarball" \
|
|
78
|
+
"https://github.com/rtk-ai/rtk/releases/download/v${RTK_VERSION}/rtk-x86_64-unknown-linux-musl.tar.gz"
|
|
79
|
+
echo "${RTK_SHA256} $tarball" | sha256sum --check --strict
|
|
80
|
+
|
|
81
|
+
tar -xzf "$tarball" -C "$RUNNER_TEMP"
|
|
82
|
+
mkdir -p "$HOME/.local/bin"
|
|
83
|
+
install -m 0755 "$RUNNER_TEMP/rtk" "$HOME/.local/bin/rtk"
|
|
84
|
+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
85
|
+
|
|
86
|
+
rtk --version
|
|
87
|
+
rtk init -g --opencode --auto-patch
|
|
88
|
+
|
|
89
|
+
- name: Install agentmemory
|
|
90
|
+
run: |
|
|
91
|
+
set -euo pipefail
|
|
92
|
+
|
|
93
|
+
if command -v agentmemory > /dev/null 2>&1 && agentmemory --version 2>/dev/null | grep -q "${AGENTMEMORY_VERSION}"; then
|
|
94
|
+
echo "agentmemory ${AGENTMEMORY_VERSION} already installed"
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
npm install -g "@agentmemory/agentmemory@${AGENTMEMORY_VERSION}"
|
|
99
|
+
agentmemory --version
|
|
100
|
+
|
|
101
|
+
- name: Restore the CodeGraph index
|
|
102
|
+
# Ephemeral ARC runners start empty, so without this every run rebuilds the whole graph.
|
|
103
|
+
# actions/cache is repository-scoped by design, which keeps consumers isolated, and
|
|
104
|
+
# each run saves an immutable snapshot under its own key at job end (the action's built-in
|
|
105
|
+
# post step), so two concurrent runs never write the same entry: the newest snapshot simply
|
|
106
|
+
# wins the next restore. The index lives in .codegraph inside the checkout plus a small
|
|
107
|
+
# registry in ~/.codegraph.
|
|
108
|
+
uses: actions/cache@v4
|
|
109
|
+
with:
|
|
110
|
+
path: |
|
|
111
|
+
.codegraph
|
|
112
|
+
~/.codegraph
|
|
113
|
+
key: codegraph-${{ github.repository_id }}-${{ github.run_id }}
|
|
114
|
+
restore-keys: |
|
|
115
|
+
codegraph-${{ github.repository_id }}-
|
|
116
|
+
|
|
117
|
+
- name: Install codegraph and index the repository
|
|
118
|
+
continue-on-error: true
|
|
119
|
+
run: |
|
|
120
|
+
set -euo pipefail
|
|
121
|
+
|
|
122
|
+
if command -v codegraph > /dev/null 2>&1 && codegraph --version 2>/dev/null | grep -q "${CODEGRAPH_VERSION}"; then
|
|
123
|
+
echo "codegraph ${CODEGRAPH_VERSION} already installed"
|
|
124
|
+
else
|
|
125
|
+
npm install -g "@colbymchenry/codegraph@${CODEGRAPH_VERSION}"
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
codegraph init
|
|
129
|
+
|
|
130
|
+
- name: Install OpenSpec CLI
|
|
131
|
+
run: |
|
|
132
|
+
set -euo pipefail
|
|
133
|
+
|
|
134
|
+
if command -v openspec > /dev/null 2>&1 && openspec --version 2>/dev/null | grep -q "1.8.0"; then
|
|
135
|
+
echo "openspec 1.8.0 already installed"
|
|
136
|
+
exit 0
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
npm install -g "@fission-ai/openspec@1.8.0"
|
|
140
|
+
openspec --version
|
|
141
|
+
|
|
142
|
+
# NOTE: playwright-cli and SQL Server startup steps are not part of the shared CI
|
|
143
|
+
# baseline. The agent path captures no visual evidence: it cannot reach a browser
|
|
144
|
+
# from inside the awf sandbox, and a screenshot with no baseline to compare against
|
|
145
|
+
# gated nothing. Run /ops-evidence locally when a change warrants screenshots. If
|
|
146
|
+
# you need playwright-cli or SQL Server inside the agent sandbox for other reasons,
|
|
147
|
+
# add them as consumer-specific steps after the shared baseline.
|
|
148
|
+
|
|
149
|
+
- name: Setup .NET
|
|
150
|
+
# Ephemeral VMs carry no SDK; the old host had it baked in, and GitHub-hosted images made
|
|
151
|
+
# the dependency invisible. setup-dotnet caches per run from the MS CDN.
|
|
152
|
+
uses: actions/setup-dotnet@v5
|
|
153
|
+
with:
|
|
154
|
+
dotnet-version: 10.0.x
|
|
155
|
+
env:
|
|
156
|
+
# the default /usr/share/dotnet needs root; the tool cache belongs to the runner user
|
|
157
|
+
DOTNET_INSTALL_DIR: ${{ runner.tool_cache }}/dotnet
|
|
158
|
+
|
|
159
|
+
- name: Cache NuGet packages
|
|
160
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
161
|
+
with:
|
|
162
|
+
path: ~/.nuget/packages
|
|
163
|
+
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.slnx', '**/Directory.Packages.props') }}
|
|
164
|
+
restore-keys: nuget-${{ runner.os }}-
|
|
165
|
+
|
|
166
|
+
- name: Install workspace dependencies
|
|
167
|
+
run: pnpm install --frozen-lockfile
|
|
168
|
+
|
|
169
|
+
- name: Merge the CI-only OpenCode provider into opencode.jsonc
|
|
170
|
+
run: |
|
|
171
|
+
set -euo pipefail
|
|
172
|
+
|
|
173
|
+
CONFIG=opencode.jsonc
|
|
174
|
+
FRAGMENT=opencode.ci.json
|
|
175
|
+
|
|
176
|
+
[ -f "$FRAGMENT" ] || { echo "::error::$FRAGMENT is missing from the checkout"; exit 1; }
|
|
177
|
+
|
|
178
|
+
# Pure JSON on purpose, not JSONC: jq cannot parse `//` comments, and a naive
|
|
179
|
+
# comment-stripper would corrupt the `http://` inside the provider's api URL.
|
|
180
|
+
jq -e . "$FRAGMENT" > /dev/null \
|
|
181
|
+
|| { echo "::error::$FRAGMENT is not valid JSON. Comments are not allowed in it."; exit 1; }
|
|
182
|
+
|
|
183
|
+
# Despite the .jsonc name, this file is committed in this repository and is read by
|
|
184
|
+
# jq below, so it must contain no comments. A single `//` line fails the merge with
|
|
185
|
+
# "Invalid numeric literal", which names neither the file nor the reason.
|
|
186
|
+
if [ -f "$CONFIG" ] && ! jq -e . "$CONFIG" > /dev/null 2>&1; then
|
|
187
|
+
echo "::error::$CONFIG is tracked and must be comment-free JSON: jq cannot parse it."
|
|
188
|
+
exit 1
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
# opencode.jsonc is untracked in most repositories, so it usually does not exist here.
|
|
192
|
+
# Create it from the fragment when absent, merge when a checkout did provide one.
|
|
193
|
+
if [ -f "$CONFIG" ]; then
|
|
194
|
+
merged=$(jq -s '.[0] * .[1]' "$CONFIG" "$FRAGMENT")
|
|
195
|
+
else
|
|
196
|
+
merged=$(jq -S . "$FRAGMENT")
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
printf '%s\n' "$merged" > "$CONFIG"
|
|
200
|
+
|
|
201
|
+
# gh-aw's own "Write OpenCode Config" step runs next and merges its base config with
|
|
202
|
+
# `$existing * $base`. Base wins on conflicting keys, but it defines neither `model`
|
|
203
|
+
# nor this provider, so both survive and `awf-proxy` is added alongside.
|
|
204
|
+
echo "Wrote $CONFIG from $FRAGMENT:"
|
|
205
|
+
jq -r '" model: \(.model // "unset")", " plugins: \(.plugin // [] | join(", "))", " providers: \(.provider // {} | keys | join(", "))"' "$CONFIG"
|
|
206
|
+
---
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
---
|
|
2
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/shared/platform-defaults.md. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
3
|
-
description: Shared network and safe-output defaults for catalog agent workflows, plus the verification rules every worker that builds or pushes has to follow. The body below is runtime-imported into each worker's prompt ahead of its own steps.
|
|
4
|
-
|
|
5
|
-
network:
|
|
6
|
-
allowed:
|
|
7
|
-
- defaults
|
|
8
|
-
- forge.plainconcepts.com
|
|
9
|
-
- node
|
|
10
|
-
- github
|
|
11
|
-
- dotnet
|
|
12
|
-
- fonts
|
|
13
|
-
- login.microsoftonline.com
|
|
14
|
-
# centralised AgentMemory (App Service); the MCP shim needs it through the egress proxy
|
|
15
|
-
- agentmemory-pro-01.azurewebsites.net
|
|
16
|
-
|
|
17
|
-
safe-outputs:
|
|
18
|
-
threat-detection: false
|
|
19
|
-
---
|
|
1
|
+
---
|
|
2
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/shared/platform-defaults.md. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
3
|
+
description: Shared network and safe-output defaults for catalog agent workflows, plus the verification rules every worker that builds or pushes has to follow. The body below is runtime-imported into each worker's prompt ahead of its own steps.
|
|
4
|
+
|
|
5
|
+
network:
|
|
6
|
+
allowed:
|
|
7
|
+
- defaults
|
|
8
|
+
- forge.plainconcepts.com
|
|
9
|
+
- node
|
|
10
|
+
- github
|
|
11
|
+
- dotnet
|
|
12
|
+
- fonts
|
|
13
|
+
- login.microsoftonline.com
|
|
14
|
+
# centralised AgentMemory (App Service); the MCP shim needs it through the egress proxy
|
|
15
|
+
- agentmemory-pro-01.azurewebsites.net
|
|
16
|
+
|
|
17
|
+
safe-outputs:
|
|
18
|
+
threat-detection: false
|
|
19
|
+
---
|
|
20
20
|
|
|
21
21
|
## Verification, for every worker that builds or pushes
|
|
22
22
|
|
|
@@ -242,7 +242,7 @@ permissions:
|
|
|
242
242
|
jobs:
|
|
243
243
|
# Public repositories must check repository permission before an event can start a model.
|
|
244
244
|
authorize:
|
|
245
|
-
runs-on:
|
|
245
|
+
runs-on: RunnerLandingZone
|
|
246
246
|
timeout-minutes: 5
|
|
247
247
|
permissions:
|
|
248
248
|
contents: read
|
|
@@ -345,7 +345,7 @@ jobs:
|
|
|
345
345
|
esac
|
|
346
346
|
|
|
347
347
|
classify:
|
|
348
|
-
runs-on:
|
|
348
|
+
runs-on: RunnerLandingZone
|
|
349
349
|
timeout-minutes: 5
|
|
350
350
|
permissions:
|
|
351
351
|
contents: read
|
|
@@ -402,7 +402,7 @@ jobs:
|
|
|
402
402
|
check-implement-pr:
|
|
403
403
|
needs: [classify, authorize]
|
|
404
404
|
if: needs.classify.outputs.route == 'implement' && needs.authorize.outputs.trusted == 'true'
|
|
405
|
-
runs-on:
|
|
405
|
+
runs-on: RunnerLandingZone
|
|
406
406
|
timeout-minutes: 3
|
|
407
407
|
permissions:
|
|
408
408
|
contents: read
|
|
@@ -493,7 +493,7 @@ jobs:
|
|
|
493
493
|
dispatch-triage:
|
|
494
494
|
needs: [classify, authorize]
|
|
495
495
|
if: needs.classify.outputs.route == 'triage' && needs.authorize.outputs.is_outside_collaborator == 'true'
|
|
496
|
-
runs-on:
|
|
496
|
+
runs-on: RunnerLandingZone
|
|
497
497
|
timeout-minutes: 5
|
|
498
498
|
permissions:
|
|
499
499
|
actions: write
|
|
@@ -621,7 +621,7 @@ jobs:
|
|
|
621
621
|
if: >
|
|
622
622
|
needs.classify.outputs.route == 'bot-approve' &&
|
|
623
623
|
(github.actor == 'app/github-actions' || github.actor == 'platform-devbox[bot]')
|
|
624
|
-
runs-on:
|
|
624
|
+
runs-on: RunnerLandingZone
|
|
625
625
|
timeout-minutes: 5
|
|
626
626
|
permissions:
|
|
627
627
|
actions: write
|
|
@@ -678,7 +678,7 @@ jobs:
|
|
|
678
678
|
github.event.pull_request.head.repo.full_name == github.repository
|
|
679
679
|
)
|
|
680
680
|
)
|
|
681
|
-
runs-on:
|
|
681
|
+
runs-on: RunnerLandingZone
|
|
682
682
|
timeout-minutes: 10
|
|
683
683
|
permissions:
|
|
684
684
|
contents: read
|
|
@@ -871,7 +871,7 @@ jobs:
|
|
|
871
871
|
reconcile-bot-pr-runs:
|
|
872
872
|
needs: classify
|
|
873
873
|
if: needs.classify.outputs.route == 'reconcile-bot-pr-runs'
|
|
874
|
-
runs-on:
|
|
874
|
+
runs-on: RunnerLandingZone
|
|
875
875
|
timeout-minutes: 5
|
|
876
876
|
permissions:
|
|
877
877
|
contents: read
|
|
@@ -1079,12 +1079,26 @@ jobs:
|
|
|
1079
1079
|
-f "inputs[ci-conclusion]=$ci_conclusion" \
|
|
1080
1080
|
-f "inputs[ci-run-id]=$ci_run_id" \
|
|
1081
1081
|
-f "inputs[attempts_so_far]=$attempts"
|
|
1082
|
+
|
|
1083
|
+
# One gate per tick, because that is all the concurrency group can hold. The gate
|
|
1084
|
+
# runs in `merge-belt`, and GitHub keeps only the most recent *pending* run in a
|
|
1085
|
+
# group -- `cancel-in-progress: false` does not change that, it only protects a run
|
|
1086
|
+
# that has already started. A tick that dispatched three gates therefore ran the
|
|
1087
|
+
# last and silently cancelled the other two: no comment, no attempt recorded, and
|
|
1088
|
+
# nothing on the pull request to say it had been passed over. Seen on Pliny-Bot,
|
|
1089
|
+
# where dispatching a gate for PR #135 cancelled the one queued for PR #136.
|
|
1090
|
+
#
|
|
1091
|
+
# Stopping here loses nothing: every pull request eligible this tick is still
|
|
1092
|
+
# eligible next tick, and a run that never started consumes no attempt. The belt
|
|
1093
|
+
# now does one thing and says so, instead of appearing to start work it discarded.
|
|
1094
|
+
echo "One gate dispatched this tick; any other eligible pull request waits for the next one."
|
|
1095
|
+
break
|
|
1082
1096
|
done
|
|
1083
1097
|
|
|
1084
1098
|
audit-close:
|
|
1085
1099
|
needs: classify
|
|
1086
1100
|
if: needs.classify.outputs.route == 'audit-close'
|
|
1087
|
-
runs-on:
|
|
1101
|
+
runs-on: RunnerLandingZone
|
|
1088
1102
|
timeout-minutes: 15
|
|
1089
1103
|
concurrency:
|
|
1090
1104
|
group: audit-close
|
|
@@ -1109,7 +1123,7 @@ jobs:
|
|
|
1109
1123
|
cleanup-artifacts:
|
|
1110
1124
|
needs: classify
|
|
1111
1125
|
if: needs.classify.outputs.route == 'cleanup-artifacts' && !github.event.repository.fork
|
|
1112
|
-
runs-on:
|
|
1126
|
+
runs-on: RunnerLandingZone
|
|
1113
1127
|
timeout-minutes: 15
|
|
1114
1128
|
concurrency:
|
|
1115
1129
|
group: cleanup-artifacts
|
|
@@ -1133,7 +1147,7 @@ jobs:
|
|
|
1133
1147
|
housekeeping:
|
|
1134
1148
|
needs: classify
|
|
1135
1149
|
if: needs.classify.outputs.route == 'housekeeping' && !github.event.repository.fork
|
|
1136
|
-
runs-on:
|
|
1150
|
+
runs-on: RunnerLandingZone
|
|
1137
1151
|
timeout-minutes: 15
|
|
1138
1152
|
concurrency:
|
|
1139
1153
|
group: housekeeping
|
|
@@ -1172,7 +1186,7 @@ jobs:
|
|
|
1172
1186
|
validate:
|
|
1173
1187
|
needs: classify
|
|
1174
1188
|
if: needs.classify.outputs.route == 'validate'
|
|
1175
|
-
runs-on:
|
|
1189
|
+
runs-on: RunnerLandingZone
|
|
1176
1190
|
timeout-minutes: 10
|
|
1177
1191
|
permissions:
|
|
1178
1192
|
contents: read
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plainconceptsplatform/workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Install and update Platform GitHub agentic workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-actions",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"README.md"
|
|
27
27
|
],
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "tsc --project tsconfig.build.json",
|
|
29
|
+
"build": "tsc --project tsconfig.build.json && node ./scripts/copy-loops.mjs",
|
|
30
30
|
"test": "vitest run",
|
|
31
31
|
"typecheck": "tsc --noEmit --project tsconfig.json",
|
|
32
32
|
"release": "pnpm build && pnpm test && npm publish --access public",
|