Skip to content

Commit 2436aec

Browse files
PeliCopilot
authored andcommitted
Use literal printf pipelines for SDK-compatible Rig launches
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 343bd04 commit 2436aec

8 files changed

Lines changed: 123 additions & 94 deletions

File tree

‎.github/workflows/rig-skill-integration.lock.yml‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.github/workflows/rig-skill-integration.md‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ timeout-minutes: 10
2222
env:
2323
RIG_DEBUG: "agent:failure,workflow:event"
2424
tools:
25-
bash: ["node"]
25+
bash: ["printf", "node"]
2626
edit: false
2727
safe-outputs:
2828
noop:
@@ -50,29 +50,29 @@ post-steps:
5050
# Rig skill integration
5151

5252
Execute this prevalidated fixture, not a setup or environment-diagnosis task.
53-
Bash execution is enabled for `node`. Your only Bash invocation must be the
54-
standalone Node launch below; a denial of another command does not mean Bash
53+
Bash execution is enabled for `printf` and `node`. Your only Bash invocation must
54+
be the launch pipeline below; a denial of another command does not mean Bash
5555
or Node is unavailable.
5656

5757
1. Load the installed `rig` skill. Read `.github/skills/rig/SKILL.md` and
5858
`.github/skills/rig/runtime.md` with file-reading tools, not Bash commands.
59-
2. Choose a fresh 7-character pseudo-random alphanumeric delimiter yourself
60-
while composing the command, without a tool call. Verify it is not a complete
61-
line of the fence contents; regenerate on collision. Do not use Python,
62-
Node, `/dev/urandom`, `base64`, `tr`, or a shell pipeline to generate it.
63-
3. Run the following `rig` fence **once**, unchanged, by substituting its contents
64-
into the command below. Replace both `<delimiter>` placeholders with the
65-
same literal seven characters. Single-quote the opening delimiter and put
66-
the unquoted closing delimiter alone on an unindented line.
59+
2. Copy the following `rig` fence **unchanged** into one single-quoted `printf`
60+
argument per source line, including `''` for blank lines. Escape each literal
61+
apostrophe as `'"'"'`. Use the fixed format `'%s\n'`, not the source as a format
62+
string; preserve percent signs, backslashes, dollar signs, and backticks.
63+
Do not double-quote source, encode it, use shell variables or substitutions,
64+
or generate delimiters. Do not use a heredoc with the Copilot SDK driver.
65+
3. Run the fence **once** using this pipeline. Replace the placeholder argument
66+
with all source-line arguments, without markdown fence markers:
6767

6868
```bash
69-
node .github/skills/rig/run.ts <<'<delimiter>' > /tmp/gh-aw/agent/rig-skill-integration.json
70-
<contents of the rig fence below, without the markdown fence markers>
71-
<delimiter>
69+
printf '%s\n' \
70+
'<one single-quoted argument per source line of the rig fence>' \
71+
| node .github/skills/rig/run.ts > /tmp/gh-aw/agent/rig-skill-integration.json
7272
```
7373

74-
The command must begin with `node`. Do not prepend `mkdir`, `cd`, `env`, `export`,
75-
or any command joined by `&&`; do not use a fixed delimiter or a shell variable.
74+
The command must begin with `printf`. Do not prepend `mkdir`, `cd`, `env`, `export`,
75+
or any command joined by `&&`.
7676
The working directory is already the repository root, `/tmp/gh-aw/agent`
7777
already exists, and Node.js and SDK dependencies are already provisioned.
7878
Do not run version checks, dependency checks, package installation, linting,
@@ -127,7 +127,7 @@ and call `noop` with a brief summary of the three judgments and majority verdict
127127
Do not invoke Bash again to read or validate the result: the post-step owns
128128
validation. Success requires no repository write. If the launcher,
129129
SDK, schema validation, or expected verdict fails, report the exact error with
130-
`report_incomplete` and stop. Never call `noop` on failure. A rejected standalone Node heredoc
131-
is a permission-parser failure, not evidence that Node or the SDK is missing.
130+
`report_incomplete` and stop. Never call `noop` on failure. A rejected launch pipeline
131+
is a permission failure, not evidence that Node or the SDK is missing.
132132
Do not fabricate results, modify the fixture, or retry model calls. The
133133
post-step fails the workflow when the result file is missing or invalid.

‎.github/workflows/shared/rig.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ runtimes:
33
node:
44
version: "24"
55
tools:
6-
bash: ["node"]
6+
bash: ["printf", "node"]
77
network:
88
allowed: [defaults, github, node]
99
---
@@ -20,10 +20,11 @@ Load the installed `rig` skill and read its Running and engines reference before
2020
creating or running Rig programs.
2121
Run Rig programs with Node.js 24 or later using the installed skill's `run.ts`
2222
launcher and host-provisioned dependencies. Do not install packages from the
23-
agent prompt; report missing dependencies and stop. Use heredocs and redirections
24-
for inline programs and output files, following the skill's fresh-delimiter rules.
25-
Choose the 7-character delimiter yourself without a tool call. Start the launch
26-
command with `node`; do not prepend `mkdir`, `cd`, `env`, or any `&&` preparation.
23+
agent prompt; report missing dependencies and stop. Pipe literal source using
24+
`printf '%s\n' ... | node <skill-dir>/run.ts`, with one single-quoted argument
25+
per line and each literal apostrophe escaped as `'"'"'`. Do not use heredocs
26+
with the Copilot SDK driver. Start the pipeline with `printf`; do not prepend
27+
`mkdir`, `cd`, `env`, or any `&&` preparation.
2728
Use existing output directories; `/tmp/gh-aw/agent` is already provisioned.
2829
Read only named environment variables needed by the program; do not dump the
2930
environment or print credentials.

‎README.md‎

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,17 @@ engine:
5656
skills:
5757
- githubnext/rig/skills/rig/SKILL.md@<full-commit-sha>
5858
tools:
59-
bash: ["node"]
59+
bash: ["printf", "node"]
6060
```
6161
6262
The [shared Rig template](.github/workflows/shared/rig.md) provisions Node.js 24
63-
and allows `node`. In this repository, import
63+
and allows `printf` and `node`. In this repository, import
6464
`shared/rig.md` instead. Without the template, configure these prerequisites
6565
explicitly; see the [runtime reference](skills/rig/runtime.md#github-agentic-workflows).
6666
Grant `copilot-requests: write` and provision the skill's dependencies in the host.
67-
Use heredocs or redirections rather than `cat`/`echo` pipelines. Grant additional
67+
For Copilot SDK workflows, use `printf '%s\n' ... | node` rather than heredocs,
68+
which gh-aw v0.91.1's SDK permission parser rejects. Single-quote each source
69+
line and escape literal apostrophes as `'"'"'`. Grant additional
6870
commands only for the program's own tool calls. This is a smaller tool
6971
allowlist, not a security boundary: Node can still start subprocesses.
7072

@@ -122,19 +124,18 @@ Its [integration guide](skills/rig/runtime.md#choosing-an-integration)
122124
compares engine capabilities, model selection, tool ownership, and output
123125
enforcement.
124126

125-
For every heredoc below, replace `<delimiter>` with a fresh 7-character
126-
pseudo-random alphanumeric string; no tool call is needed to generate it.
127-
Check it is not an entire line of the contents, single-quote the opener, and
128-
repeat the exact unquoted delimiter alone on the closing line. See the
129-
[inline-program guide](skills/rig/runtime.md#inline-programs) for the
130-
delimiter rules; do not reuse fixed delimiters or shell variables.
127+
Use the fixed `printf '%s\n'` format with one single-quoted argument per source
128+
line. Escape literal apostrophes as `'"'"'`; do not use source as the format
129+
string or double-quote it. See the
130+
[inline-program guide](skills/rig/runtime.md#inline-programs) for quoting rules
131+
and heredoc alternatives outside the Copilot SDK workflow driver.
131132

132133
**Design on the fly** — just describe what you want as a string and let the model figure out the rest:
133134

134135
```bash
135-
node skills/rig/run.ts <<'<delimiter>'
136-
export default "Run npm test, diagnose any failures, apply the smallest safe fix, and repeat up to 3 times.";
137-
<delimiter>
136+
printf '%s\n' \
137+
'export default "Run npm test, diagnose any failures, apply the smallest safe fix, and repeat up to 3 times.";' \
138+
| node skills/rig/run.ts
138139
```
139140

140141
Or ask Copilot (with the skill) to generate a full program for you. Describe your goal in natural language and Copilot returns a runnable `rig` markdown fence like this:
@@ -166,20 +167,18 @@ export default ralfLoop;
166167
```
167168
````
168169

169-
Pass the fence contents directly to the launcher with a heredoc:
170+
Pass the fence contents directly to the launcher with a literal pipeline:
170171

171172
```bash
172-
node skills/rig/run.ts <<'<delimiter>'
173-
// Paste the rig fence contents here.
174-
<delimiter>
173+
printf '%s\n' \
174+
'<one single-quoted argument per source line of the rig fence>' \
175+
| node skills/rig/run.ts
175176
```
176177

177178
Or run a program file:
178179

179180
```bash
180-
node skills/rig/run.ts src/program.ts <<'<delimiter>'
181-
Review this diff
182-
<delimiter>
181+
printf '%s\n' 'Review this diff' | node skills/rig/run.ts src/program.ts
183182
```
184183

185184
Use `--typecheck` to validate a program without running it:

‎skills/rig/SKILL.md‎

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,23 +99,19 @@ node skills/rig/run.ts --typecheck < program.ts
9999
```
100100

101101
For an installed skill, replace `skills/rig` with its installed directory. Use
102-
`run.ts` to launch without installing packages; inline programs use
103-
`node <skill-dir>/run.ts <<'<delimiter>'`. For each heredoc, generate a fresh
104-
7-character pseudo-random alphanumeric delimiter without a tool call.
105-
Choose the seven characters yourself in the response; do not execute Python,
106-
Node, `/dev/urandom`, or a shell pipeline to generate them.
107-
Ensure it is not a complete line in the contents; regenerate on collision.
108-
Single-quote the opening delimiter and repeat the same literal, unquoted
109-
delimiter alone on the closing line. Never use a fixed delimiter or shell
110-
variable; see [Running and engines](./runtime.md).
102+
`run.ts` to launch without installing packages. For Copilot SDK workflows, pipe
103+
literal source with `printf '%s\n' '<source line>' ... | node <skill-dir>/run.ts`.
104+
Use one single-quoted argument per source line, escaping each literal apostrophe
105+
as `'"'"'`. Keep `%s\n` as the fixed format; never use source as a format string,
106+
double-quote source, or expand shell variables. Do not use heredocs with the
107+
SDK driver; see [Running and engines](./runtime.md) for quoting and alternatives.
111108
Install the skill with `gh skill install githubnext/rig rig`.
112109
Assume SDKs are already installed in the agent container; do not install them.
113-
Only `node` needs a Bash tool grant for launching an installed skill; grant
114-
additional commands only when the program itself needs them.
115-
The launch command must begin with `node`: no `mkdir`, `cd`, `env`, package
116-
manager, or other preparatory command, and no `&&` prefix. Use existing output
117-
directories and inherit the SDK environment. A denial of another command does
118-
not disable Bash or `node`; report the denied command accurately.
110+
Import the shared Rig workflow template or explicitly allow `printf` and `node`
111+
with `bash: ["printf", "node"]`. Grant other commands only when the program needs
112+
them. The launch pipeline must begin with `printf`: no `mkdir`, `cd`, `env`,
113+
package manager, or other preparation, and no `&&` prefix. Use existing output
114+
directories and inherit the SDK environment. Report denied commands accurately.
119115

120116
## Final check
121117

‎skills/rig/runtime.md‎

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,26 @@ Read this reference when launching or typechecking programs, handling stdin, or
44

55
## Inline programs
66

7-
Treat a fenced `rig` block as a runnable program. Pass its contents to the launcher with a heredoc:
7+
Treat a fenced `rig` block as a runnable program. For Copilot SDK workflows,
8+
pass its contents to the launcher through a literal `printf` pipeline:
9+
10+
```bash
11+
printf '%s\n' \
12+
'// Agent role: summarize this repository in one sentence.' \
13+
'export default "Summarize this repository in one sentence.";' \
14+
| node skills/rig/run.ts
15+
```
16+
17+
Use one single-quoted argument per source line, including `''` for empty lines.
18+
Escape each literal apostrophe as `'"'"'`; for example, the source line
19+
`const label = "don't";` becomes `'const label = "don'"'"'t";'`.
20+
Always use the fixed format `'%s\n'`, never the source as a format string.
21+
This preserves percent signs, backslashes, dollar signs, and backticks literally.
22+
Do not double-quote source, expand variables, encode it, or execute substitutions.
23+
Each argument emits its original line followed by a newline. Copy the whole
24+
fence without markdown markers; do not rewrite the TypeScript.
25+
26+
Heredocs remain an alternative outside the Copilot SDK workflow driver:
827

928
Before constructing each heredoc command, generate a fresh 7-character
1029
pseudo-random alphanumeric string to use as the delimiter. Choose the seven
@@ -53,11 +72,11 @@ container. Do not attempt to install them from the driver or agent prompt.
5372
Missing dependencies stop the run with a nonzero exit and an error on stderr.
5473
`rig.ts` remains the direct runtime entry point. Node.js 24 or later is required.
5574
56-
For agentic workflows, the launch Bash allowlist is just
57-
`bash: ["node"]`. Heredocs and input/output redirections avoid `cat`, `echo`,
58-
and separate file-creation commands. Neither launch nor typechecking invokes
75+
For inline agentic workflows, explicitly grant both stages with
76+
`bash: ["printf", "node"]`, or import the shared Rig template below. This avoids
77+
`cat`, `echo`, and separate file-creation commands. Neither launch nor typechecking invokes
5978
npm or npx, and neither downloads dependencies.
60-
Start the launch command directly with `node`; do not prepend `mkdir`, `cd`,
79+
Start the inline launch pipeline with `printf`; do not prepend `mkdir`, `cd`,
6180
`env`, dependency checks, or any other command with `&&`. Read the installed
6281
skill and its reference with file-reading tools, not shell bootstrap commands.
6382
For a provided, unchanged, prevalidated fixture, skip lint and typecheck
@@ -69,17 +88,15 @@ Redirect output only into an existing directory. In GitHub Agentic Workflows,
6988
required directory is missing, report that prerequisite instead of adding a
7089
disallowed preparation command. Inherit SDK environment variables without
7190
`env` or `export` commands. If an unrelated command is denied before the launcher
72-
runs, remove that command and use the permitted standalone Node launch; do not
91+
runs, remove that command and use the permitted `printf` plus `node` pipeline; do not
7392
claim that Bash is unavailable. If the launcher itself fails, report its exact
7493
error and respect the workflow's retry policy.
7594
7695
GitHub Agentic Workflows v0.91.1's Copilot SDK permission parser treats heredoc
77-
body lines as shell commands. It can therefore reject a valid standalone
78-
`node` launch despite `bash: ["node"]`. If this happens, report the exact denial
79-
as a workflow permission-parser limitation, not a missing Node runtime or SDK.
80-
Do not broaden the shell allowlist or encode the program to evade enforcement.
81-
The workflow host needs a heredoc-aware permission parser before this inline
82-
launch pattern can run in that SDK driver.
96+
body lines as shell commands. Use the explicitly permitted `printf` plus `node`
97+
pipeline instead, not a heredoc or a blanket shell grant. If either stage is
98+
denied, report the exact command and required grant, not a missing Node runtime
99+
or SDK. Respect the workflow's retry policy.
83100
84101
This reduces tool configuration, not sandbox permissions: allowing arbitrary
85102
Node code still permits filesystem and subprocess operations. Add commands
@@ -90,9 +107,7 @@ required by the program's own tool calls separately.
90107
Export the root and pass stdin plus the file path:
91108
92109
```bash
93-
node skills/rig/run.ts src/program.ts <<'<delimiter>'
94-
Review this diff
95-
<delimiter>
110+
printf '%s\n' 'Review this diff' | node skills/rig/run.ts src/program.ts
96111
```
97112
98113
Stdin coercion follows the root schema:
@@ -146,7 +161,7 @@ engine:
146161
skills:
147162
- githubnext/rig/skills/rig/SKILL.md@<full-commit-sha>
148163
tools:
149-
bash: ["node"]
164+
bash: ["printf", "node"]
150165
```
151166
152167
Import `configureAgent` and `copilotEngine` in the fenced program and call `configureAgent(copilotEngine())` before defining agents. Launch with the installed skill's `run.ts` and host-provisioned dependencies. Grant `copilot-requests: write`, and enable only the additional tools and network access the program uses.
@@ -159,7 +174,7 @@ runtimes:
159174
node:
160175
version: "24"
161176
tools:
162-
bash: ["node"]
177+
bash: ["printf", "node"]
163178
network:
164179
allowed: [defaults, github, node]
165180
```

0 commit comments

Comments
 (0)