@sjawhar/claude-envoy 0.0.0 → 1.0.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/.claude-plugin/plugin.json +6 -0
- package/.mcp.json +11 -0
- package/.omp-plugin/plugin.json +6 -0
- package/AGENTS.md +343 -0
- package/README.md +639 -0
- package/bin/dispatch +6 -0
- package/bin/envoy-channel.ts +9 -0
- package/bin/envoy-send.ts +33 -0
- package/dist/THIRD_PARTY_NOTICES +816 -0
- package/dist/dispatch.js +27707 -0
- package/dist/envoy-channel.js +57695 -0
- package/dist/session-hook.js +26328 -0
- package/dist/session-title-hook.js +116 -0
- package/hooks/hooks.json +60 -0
- package/hooks/session-hook.ts +512 -0
- package/hooks/session-title-hook.ts +46 -0
- package/legion/.claude-plugin/plugin.json +4 -0
- package/legion/agents/deep-worker.md +68 -0
- package/legion/agents/oracle.md +35 -0
- package/legion/agents/plan-gap-analyst.md +65 -0
- package/legion/agents/plan-reviewer.md +104 -0
- package/legion/agents/thermonuclear-code-quality.md +30 -0
- package/legion/agents/thermonuclear-deep-review.md +30 -0
- package/legion/hooks/hooks.json +89 -0
- package/legion/skills/ce-simplify-code/LICENSE +21 -0
- package/legion/skills/ce-simplify-code/SKILL.md +66 -0
- package/legion/skills/ce-simplify-code/references/personas/code-quality-reviewer.md +17 -0
- package/legion/skills/ce-simplify-code/references/personas/code-reuse-reviewer.md +7 -0
- package/legion/skills/ce-simplify-code/references/personas/efficiency-reviewer.md +11 -0
- package/legion/skills/leading-a-work-stream/SKILL.md +96 -0
- package/legion/skills/leading-a-work-stream/references/daily-plan.md +8 -0
- package/legion/skills/leading-a-work-stream/references/decision-rights.md +6 -0
- package/legion/skills/leading-a-work-stream/references/direction-and-coaching.md +13 -0
- package/legion/skills/leading-a-work-stream/references/dispatch-upkeep.md +8 -0
- package/legion/skills/leading-a-work-stream/references/sources.md +9 -0
- package/legion/skills/leading-a-work-stream/references/speed-tick.md +44 -0
- package/legion/skills/leading-a-work-stream/references/user-quotes.md +7 -0
- package/legion/skills/legion-architect/SKILL.md +86 -0
- package/legion/skills/legion-architect/references/acceptance.md +208 -0
- package/legion/skills/legion-architect/references/decomposition.md +129 -0
- package/legion/skills/legion-architect/references/design-gate.md +206 -0
- package/legion/skills/legion-architect/references/merge-notices.md +91 -0
- package/legion/skills/legion-architect/references/wake-routing.md +41 -0
- package/legion/skills/legion-controller/SKILL.md +151 -0
- package/legion/skills/legion-controller/references/admission.md +22 -0
- package/legion/skills/legion-controller/references/backlog-stewardship.md +101 -0
- package/legion/skills/legion-controller/references/daily-report.md +75 -0
- package/legion/skills/legion-controller/references/escalation.md +82 -0
- package/legion/skills/legion-controller/references/finding-asks.md +181 -0
- package/legion/skills/legion-controller/references/parked-decisions.md +198 -0
- package/legion/skills/legion-controller/references/session.md +100 -0
- package/legion/skills/legion-controller/references/slack-mentions.md +154 -0
- package/legion/skills/legion-controller/references/triage.md +96 -0
- package/legion/skills/legion-controller/references/wakes.md +132 -0
- package/legion/skills/legion-oracle/SKILL.md +48 -0
- package/legion/skills/legion-retro/SKILL.md +112 -0
- package/legion/skills/legion-retro/references/learnings.md +60 -0
- package/legion/skills/legion-retro/references/pr-body-content.md +56 -0
- package/legion/skills/legion-worker/SKILL.md +69 -0
- package/legion/skills/legion-worker/references/cleanup-deletion.md +22 -0
- package/legion/skills/legion-worker/references/conflicts-and-rewrites.md +164 -0
- package/legion/skills/legion-worker/references/default-branch-check.md +53 -0
- package/legion/skills/legion-worker/references/findings.md +199 -0
- package/legion/skills/legion-worker/references/merge-gate.md +353 -0
- package/legion/skills/legion-worker/references/pr-body.md +218 -0
- package/legion/skills/legion-worker/references/review-threads.md +77 -0
- package/legion/skills/legion-worker/references/systematic-rename.md +19 -0
- package/legion/skills/legion-worker/references/tools.md +708 -0
- package/legion/skills/thermonuclear-code-quality/LICENSE +21 -0
- package/legion/skills/thermonuclear-code-quality/SKILL.md +60 -0
- package/legion/skills/thermonuclear-deep-review/LICENSE +21 -0
- package/legion/skills/thermonuclear-deep-review/SKILL.md +80 -0
- package/package.json +49 -1
- package/scripts/build-inputs.txt +84 -0
- package/scripts/build.ts +415 -0
- package/scripts/check-packed-skills.sh +50 -0
- package/scripts/pack-skills.sh +146 -0
- package/scripts/smoke-channel.sh +178 -0
- package/scripts/smoke-clear-rebind.sh +164 -0
- package/scripts/smoke-session-title.sh +245 -0
- package/scripts/verify-build.sh +88 -0
- package/skills/agent-secrets/SKILL.md +180 -0
- package/skills/asd-ste100/LICENSE +21 -0
- package/skills/asd-ste100/SKILL.md +140 -0
- package/skills/asd-ste100/examples/before-after.md +92 -0
- package/skills/asd-ste100/references/writing-rules.md +59 -0
- package/skills/dispatch/SKILL.md +89 -0
- package/skills/dispatch-first/SKILL.md +46 -0
- package/skills/dispatch-writing-specs/SKILL.md +80 -0
- package/skills/envoy/SKILL.md +82 -0
- package/skills/envoy/references/check-settlement.md +62 -0
- package/skills/envoy/references/deliveries.md +67 -0
- package/skills/envoy/references/legion.md +14 -0
- package/skills/envoy/references/roles.md +12 -0
- package/skills/envoy/references/sources.md +41 -0
- package/skills/outside-message/SKILL.md +111 -0
- package/skills/plain-words/SKILL.md +88 -0
- package/src/channel-forwarder.ts +262 -0
- package/src/claude-channel.ts +705 -0
- package/src/claude-session.ts +38 -0
- package/src/envoy-channel-server.ts +2115 -0
- package/src/envoy-client.ts +26 -0
- package/src/envoy-off.ts +62 -0
- package/src/legion-claim.ts +211 -0
- package/src/legion-inbox.ts +110 -0
- package/src/legion-phase-hook.ts +554 -0
- package/src/legion-tool.ts +69 -0
- package/src/replay-state.ts +97 -0
- package/src/send-arguments.ts +13 -0
- package/src/session-identity.ts +165 -0
- package/src/session-state.ts +142 -0
- package/src/session-title.ts +251 -0
- package/src/subscription-topics.ts +16 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-build.sh <tar> — build the plugin from this tree, check the build is one the release
|
|
3
|
+
# publishes, and pack it into <tar>, leaving the checkout as it found it.
|
|
4
|
+
#
|
|
5
|
+
# This is the one statement of what the published plugin must hold. release.yaml's
|
|
6
|
+
# claude_envoy_build runs it and then packs the tarball it publishes to npm; ci.yaml's required
|
|
7
|
+
# test job and its claude-envoy job run the very same command on a pull request, so a pull request
|
|
8
|
+
# fails a check for whatever the release would refuse instead of merging and then failing every
|
|
9
|
+
# release on main.
|
|
10
|
+
#
|
|
11
|
+
# It writes no file of the checkout: nothing commits dist/ or legion/, and jj records whatever a
|
|
12
|
+
# command writes into the working copy. Every build goes into a scratch directory outside the
|
|
13
|
+
# repository, and <tar> must be outside it too. The jobs that then put <tar> into a checkout are
|
|
14
|
+
# named at `release-push.sh extract-built`.
|
|
15
|
+
#
|
|
16
|
+
# Every file this script and scripts/build.ts read is a build input, so scripts/build-inputs.txt
|
|
17
|
+
# must name it: that list is what release.yaml's $CLAUDE_ENVOY_VERSION_ARGS covers, so a build
|
|
18
|
+
# input missing from it is one no release bumps a version for. tests/build-inputs.test.ts checks
|
|
19
|
+
# the list against what the bundles and the Legion plugin read, but not against what this script
|
|
20
|
+
# or build.ts read by path, which the list's header names as listed by hand
|
|
21
|
+
# (check-private-names.sh, release-push.sh, .bun-version, the scripts build.ts imports or runs,
|
|
22
|
+
# and setup-bun): a new file read here goes into the list by hand.
|
|
23
|
+
#
|
|
24
|
+
# In order, whatever the caller's directory:
|
|
25
|
+
# 1. `bun scripts/build.ts --out` twice, into two scratch directories, and the two builds'
|
|
26
|
+
# dist/ and legion/ compared byte for byte, so what the release publishes is what the source
|
|
27
|
+
# builds to, not one run's accident;
|
|
28
|
+
# 2. .github/scripts/check-private-names.sh over the first build, laid out at its repository
|
|
29
|
+
# path in a scratch git repository (below);
|
|
30
|
+
# 3. `tar -cf <tar>` of the first build's dist/ and legion/, the tar the build job extracts;
|
|
31
|
+
# 4. `.github/scripts/release-push.sh check-built <tar>`, the member checks: no symlink, no
|
|
32
|
+
# executable file, no name outside letters, digits, '.', '_' and '-', and every bundle and
|
|
33
|
+
# file a build holds (a skill pi-legion ships is staged into legion/ with `cp -R`, which
|
|
34
|
+
# keeps its modes and symlinks).
|
|
35
|
+
# Any failure exits non-zero.
|
|
36
|
+
#
|
|
37
|
+
# Run from packages/claude-envoy: bun run verify-build <tar outside the repository>
|
|
38
|
+
set -euo pipefail
|
|
39
|
+
|
|
40
|
+
[ $# -eq 1 ] || {
|
|
41
|
+
echo "::error::verify-build.sh: usage: verify-build.sh <tar outside the repository>" >&2
|
|
42
|
+
exit 2
|
|
43
|
+
}
|
|
44
|
+
tar_file=$1
|
|
45
|
+
|
|
46
|
+
package_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)
|
|
47
|
+
repo_root=$(cd "$package_dir/../.." && pwd -P)
|
|
48
|
+
|
|
49
|
+
# <tar>, made absolute from the caller's directory, must sit outside the repository, where jj
|
|
50
|
+
# would record it.
|
|
51
|
+
tar_dir=$(cd "$(dirname -- "$tar_file")" 2>/dev/null && pwd -P) || {
|
|
52
|
+
echo "::error::verify-build.sh: the directory of $tar_file does not exist" >&2
|
|
53
|
+
exit 2
|
|
54
|
+
}
|
|
55
|
+
tar_file=$tar_dir/$(basename -- "$tar_file")
|
|
56
|
+
case $tar_dir/ in
|
|
57
|
+
"$repo_root"/*)
|
|
58
|
+
echo "::error::verify-build.sh: $tar_file is inside the repository ($repo_root); name a tar outside it, such as under \$TMPDIR" >&2
|
|
59
|
+
exit 2
|
|
60
|
+
;;
|
|
61
|
+
esac
|
|
62
|
+
|
|
63
|
+
scratch=$(mktemp -d)
|
|
64
|
+
trap 'rm -rf "$scratch"' EXIT
|
|
65
|
+
first=$scratch/first/packages/claude-envoy
|
|
66
|
+
second=$scratch/second
|
|
67
|
+
|
|
68
|
+
cd "$package_dir"
|
|
69
|
+
bun scripts/build.ts --out "$first"
|
|
70
|
+
bun scripts/build.ts --out "$second"
|
|
71
|
+
if ! differ=$(diff -r -q "$first/dist" "$second/dist" && diff -r -q "$first/legion" "$second/legion"); then
|
|
72
|
+
echo "::error::verify-build.sh: two builds of this tree differ, so its build is not reproducible and the release would publish one run's output: ${differ//$'\n'/; }" >&2
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# The private-name check runs from a scratch git repository only so the build sits at its
|
|
77
|
+
# repository path (packages/claude-envoy/dist/envoy-channel.js, the vendored-NATS exception's
|
|
78
|
+
# path): given paths, the check reads them with find and grep, not git. It finds the repository it
|
|
79
|
+
# scans from its own path, so a link to it sits in the scratch repository, and it scans the
|
|
80
|
+
# build's two directories alone.
|
|
81
|
+
mkdir -p "$scratch/first/.github/scripts"
|
|
82
|
+
ln -s "$repo_root/.github/scripts/check-private-names.sh" "$scratch/first/.github/scripts/"
|
|
83
|
+
git -c init.defaultBranch=main init -q "$scratch/first"
|
|
84
|
+
(cd "$scratch/first" && .github/scripts/check-private-names.sh packages/claude-envoy/dist packages/claude-envoy/legion)
|
|
85
|
+
|
|
86
|
+
tar -cf "$tar_file" -C "$first" dist legion
|
|
87
|
+
"$repo_root/.github/scripts/release-push.sh" check-built "$tar_file"
|
|
88
|
+
echo "verify-build.sh: $tar_file holds a build the release publishes"
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-secrets
|
|
3
|
+
description: Use before a command that needs a token, a key or a password; before you say that a service or an API is out of reach; and when an instruction names `agent-secrets`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# agent-secrets
|
|
7
|
+
|
|
8
|
+
The secrets broker holds the credentials this deployment gives its agents. `agent-secrets` is its
|
|
9
|
+
client. It asks the broker for a secret and gives it to one command, in that command's environment.
|
|
10
|
+
Your session never holds the value, and nothing of it reaches your transcript.
|
|
11
|
+
|
|
12
|
+
## The one form
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
agent-secrets NAME... [--reason TEXT] [--wait DURATION] [--ttl DURATION] -- <command> [args...]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- Each granted secret reaches `<command>`'s environment under its own name. Nothing runs unless
|
|
19
|
+
every name is granted: a denial of one name denies the whole request, so the command never starts
|
|
20
|
+
with some of its secrets missing (`cmdExec`, `packages/envoy/cmd/agent-secrets/main.go`).
|
|
21
|
+
- `--reason` is what a person reads if the request waits for a decision. Write one.
|
|
22
|
+
- `agent-secrets --help` holds the rest: the flags that narrow a GitHub App token
|
|
23
|
+
(`--github-owner`, `--github-repo`, `--github-read-only`), and how long a grant lasts.
|
|
24
|
+
|
|
25
|
+
## The command reads the value, your shell does not
|
|
26
|
+
|
|
27
|
+
This form sends an empty value, and the API answers as if you had sent no credential:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
# wrong
|
|
31
|
+
agent-secrets LEGION_SLACK_BOT_TOKEN -- \
|
|
32
|
+
curl -sS -H "Authorization: Bearer $LEGION_SLACK_BOT_TOKEN" https://slack.com/api/auth.test
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Your own shell expands `$LEGION_SLACK_BOT_TOKEN` before `agent-secrets` runs, and in your shell that
|
|
36
|
+
name is empty. Measured on 2026-11-04 from a Legion issue pod: Slack answered
|
|
37
|
+
`{"ok":false,"error":"not_authed"}`. The value exists only in the environment of the command the
|
|
38
|
+
client starts, so that command must read it itself. Put the command in single quotes, inside
|
|
39
|
+
`sh -c`, where the quotes keep the expansion for the child:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# right
|
|
43
|
+
agent-secrets LEGION_SLACK_BOT_TOKEN -- \
|
|
44
|
+
sh -c 'curl -sS -H "Authorization: Bearer $LEGION_SLACK_BOT_TOKEN" https://slack.com/api/auth.test'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The repository uses the same form for a GitHub App token in `docs/deployment.md`:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
agent-secrets LEGION_IMPLEMENT_APP --reason=… -- sh -c 'printf %s "$LEGION_IMPLEMENT_APP"'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## The value never reaches your transcript
|
|
54
|
+
|
|
55
|
+
Your transcript keeps everything a command prints.
|
|
56
|
+
|
|
57
|
+
- Never echo or print the value, and never run `curl -v`, `curl --trace` or a shell with `set -x`
|
|
58
|
+
around it: each of those writes the header, and so the value, to your output.
|
|
59
|
+
- Check a value's shape by its length and its prefix alone:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
agent-secrets NAME -- sh -c 'echo "${#NAME}"; case "$NAME" in ghp_*) echo prefix-ok;; *) echo prefix-no;; esac'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- Compare two values only as equal or not equal. Never print, slice or diff their characters.
|
|
66
|
+
|
|
67
|
+
## Read the answer, not the status alone
|
|
68
|
+
|
|
69
|
+
Slack and most HTTP APIs answer `200` with `"ok": false`, so a call that failed can still exit 0.
|
|
70
|
+
Read the body. Send it to `jq` straight from `curl`, or through `printf '%s'`, and never through
|
|
71
|
+
`echo`: the pod's `sh` turns a `\n` inside a JSON string into a control character, which `jq` then
|
|
72
|
+
refuses.
|
|
73
|
+
|
|
74
|
+
## What the exit status means
|
|
75
|
+
|
|
76
|
+
After a grant the client writes one line to stderr, `agent-secrets: <names> from <source>`, and the
|
|
77
|
+
status is then the command's own. One case breaks that: a line `agent-secrets: exec <command>: …`
|
|
78
|
+
after it means the command could not start, and the status is 1.
|
|
79
|
+
|
|
80
|
+
Without the grant line the status is the client's own:
|
|
81
|
+
|
|
82
|
+
- **1** — a refusal or a failure that the message names: a name the broker does not serve
|
|
83
|
+
(`UNKNOWN_SECRET`), a broker it cannot reach, a machine that is not logged in to the broker, a
|
|
84
|
+
request cancelled or expired, `REQUEST_PENDING`, a grant that is no longer live, or a command
|
|
85
|
+
that is not on `PATH`.
|
|
86
|
+
- **2** — a usage error: no broker identity at all (no key in the key dir and no helper socket), no
|
|
87
|
+
`AGENT_SECRETS_URL`, no `--`, no `NAME`, or a flag value the client refuses.
|
|
88
|
+
- **75** — the request still waits for a person. The message names who decides it, where, and the
|
|
89
|
+
`agent-secrets status <request_id>` that reads it.
|
|
90
|
+
- **77** — the request was denied.
|
|
91
|
+
|
|
92
|
+
The other statuses come from forms this skill does not use: 76 from `agent-secrets renew`, a
|
|
93
|
+
refusal that is permanent; 126 and 127 from `agent-secrets register --exec`, whose command could not
|
|
94
|
+
run or was not found; and 129, 130, 131 and 143 from a signal at the value prompt of
|
|
95
|
+
`agent-secrets secret create` or `secret set`. `agent-secrets --help` lists them all.
|
|
96
|
+
|
|
97
|
+
## Waiting, and a grant you already hold
|
|
98
|
+
|
|
99
|
+
- `--wait` waits 30 minutes by default. A session that must not block passes `--wait 0s`, reads the
|
|
100
|
+
request id from the message, and reads the decision later with
|
|
101
|
+
`agent-secrets status <request_id>`.
|
|
102
|
+
- A later run with the same names and the same `--ttl` uses the live grant again and asks nobody;
|
|
103
|
+
while the first request still waits, such a run joins it. Any other run that would itself wait
|
|
104
|
+
for a person and shares a name with a waiting request, with another `--ttl` or another set of
|
|
105
|
+
names, is refused `REQUEST_PENDING`, which names the request already waiting.
|
|
106
|
+
- `agent-secrets identity` exits 0 when this session has a broker identity and 1 when it has none,
|
|
107
|
+
and it asks the broker nothing. `agent-secrets self` prints this session's live grants.
|
|
108
|
+
|
|
109
|
+
## Where a name comes from, and how you may use it
|
|
110
|
+
|
|
111
|
+
The broker tells a session no names. A name comes from your deployment instructions, your role
|
|
112
|
+
prompt, a skill, or the issue you work on. There is no list to browse and nothing to guess.
|
|
113
|
+
|
|
114
|
+
- Request a secret only to use it for the work in front of you. A request made to learn whether a
|
|
115
|
+
secret exists reaches a person's Inbox.
|
|
116
|
+
- `UNKNOWN_SECRET` and a denial are final. Do not ask again, and do not try a name of your own.
|
|
117
|
+
- A secret that a service owns, such as `LEGION_SLACK_BOT_TOKEN`, goes to that service's own pods
|
|
118
|
+
and VMs and to nothing else: `Evaluate` in `packages/envoy/internal/broker/policy/policy.go`
|
|
119
|
+
grants a service-owned secret at once when the session's own service is the secret's owner, and
|
|
120
|
+
denies every other session, with no person asked.
|
|
121
|
+
- The `agent-secrets secret` forms (`list`, `show`, `create`, `set`, `retag`, `delete`, `restore`)
|
|
122
|
+
act under a person's own cloud sign-in. They belong to the secret's owner, not to an agent.
|
|
123
|
+
- Slack's read methods go through `curl` under this client. Every post to Slack stays a `slack_post`
|
|
124
|
+
call, which holds the reply to one thread, to 4,000 characters and to one send.
|
|
125
|
+
|
|
126
|
+
## Before you say that a service is out of reach
|
|
127
|
+
|
|
128
|
+
1. Run the call through `agent-secrets`, with the secret your instructions name.
|
|
129
|
+
2. Report a service unreachable only with the command you ran and the output you saw.
|
|
130
|
+
3. When no instruction names a secret for that service, report that instead, with what you checked:
|
|
131
|
+
`agent-secrets identity`, and which instructions you read. Request no name you guessed.
|
|
132
|
+
|
|
133
|
+
## On a person's own machine
|
|
134
|
+
|
|
135
|
+
A session on a person's own development box is not a pod, and `agent-secrets identity` exits 1 there
|
|
136
|
+
for two reasons:
|
|
137
|
+
|
|
138
|
+
- **The machine is not logged in.** `agent-secrets machine login-status` prints `issued` only while
|
|
139
|
+
the machine holds its credential. The person logs the machine in; step 4b of `docs/joining.md` in
|
|
140
|
+
theorem-labs/agent-infra, "Log the VM in to the secrets broker", is that step.
|
|
141
|
+
- **The agent is not a broker session.** The helper knows only the process tree it registered. The
|
|
142
|
+
person restarts the agent as one:
|
|
143
|
+
`agent-secrets register --wait 10 --exec -- <the agent's command>`.
|
|
144
|
+
|
|
145
|
+
On `UNKNOWN_SECRET` you stop, as above. You may tell the secret's owner how to find the cause:
|
|
146
|
+
`agent-secrets secret list` and `agent-secrets secret show NAME`, under their own cloud sign-in
|
|
147
|
+
(`gcloud auth login` against a broker on Google Cloud, their `AWS_PROFILE` against one on AWS).
|
|
148
|
+
|
|
149
|
+
An owner who must store a secret does every write under their own cloud sign-in.
|
|
150
|
+
`agent-secrets secret set NAME` replaces the value of a secret that exists. A new one is
|
|
151
|
+
`agent-secrets secret create NAME --owner me|shared --tier agent|human`. Both read the value from
|
|
152
|
+
standard input or from a prompt with echo off, never from an argument. Type it at the prompt, so it
|
|
153
|
+
reaches no shell history.
|
|
154
|
+
|
|
155
|
+
## A worked example: one page of a Slack thread
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
agent-secrets LEGION_SLACK_BOT_TOKEN --reason 'read the thread of a Slack mention' --wait 0s -- sh -c '
|
|
159
|
+
curl -sS -G https://slack.com/api/conversations.replies \
|
|
160
|
+
-H "Authorization: Bearer $LEGION_SLACK_BOT_TOKEN" \
|
|
161
|
+
--data-urlencode channel=<channel_id> \
|
|
162
|
+
--data-urlencode ts=<thread_ts> \
|
|
163
|
+
--data-urlencode limit=200'
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Measured on 2026-11-04 from a Legion issue pod: it exited 0 and answered `"ok": true` with the 12
|
|
167
|
+
messages of the thread. A `ts` that names no message answers
|
|
168
|
+
`{"ok":false,"error":"thread_not_found"}`, also at exit 0, which is why the body decides and not the
|
|
169
|
+
status. A thread read needs the app's `channels:history` scope in a public channel and
|
|
170
|
+
`groups:history` in a private one; without them Slack answers `missing_scope`, which only a person
|
|
171
|
+
in the Slack workspace can fix. A session with a broker identity that is not one of the
|
|
172
|
+
`legion-daemon` service's own is denied this token, and the example exits 77; a session with no
|
|
173
|
+
broker identity exits 2.
|
|
174
|
+
|
|
175
|
+
Paging: Slack recommends a `limit` of at most 200. While the answer's `has_more` is true, pass its
|
|
176
|
+
`response_metadata.next_cursor` as `cursor` to the next call. Each page repeats the thread's root
|
|
177
|
+
message, so drop repeats by `ts` and sort by `ts`.
|
|
178
|
+
|
|
179
|
+
A message from the client that this skill does not cover is in the broker's troubleshooting guide,
|
|
180
|
+
`/legion/broker/guides/troubleshooting/` in the documentation site.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dustin Yuchen Teng
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: asd-ste100
|
|
3
|
+
description: "Use when English text must be parsed without a human to resolve ambiguity — tool descriptions, error messages, inter-agent instructions, system prompts, status reports — and misreading has a real cost, or when text reads as dense, hedged, or easy to misparse. Triggers: disambiguate, STE100 rewrite, apply Simplified Technical English, plain-language rewrite, controlled-language rewrite, rewrite so an agent cannot misread this. Not for creative or marketing copy."
|
|
4
|
+
version: 0.4.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Copied from danyuchn/asd-ste100-skill at 32511c69 under its MIT licence (LICENSE), without its linter.
|
|
8
|
+
|
|
9
|
+
# Simplified Technical English (ASD-STE100)
|
|
10
|
+
|
|
11
|
+
ASD-STE100 is a controlled-language standard built by the aerospace and defense industry (ASD, the AeroSpace and Defense Industries Association of Europe) to stop maintenance technicians from misreading English instructions. The standard removes the two biggest sources of misreading: words with more than one meaning, and sentences with more than one possible structure.
|
|
12
|
+
|
|
13
|
+
This skill borrows that same discipline for a different reader: an **AI agent or a downstream system** that has to parse an English string — an error message, a tool description, an inter-agent instruction, a status report — without a human in the loop to resolve ambiguity. If a maintenance technician can misread "close the valve" as an adjective ("the valve that is near") instead of a command, so can a language model.
|
|
14
|
+
|
|
15
|
+
## When to Use This Skill
|
|
16
|
+
|
|
17
|
+
- An agent's output (explanation, instruction, log message, tool description) reads as dense, jargon-heavy, or ambiguous.
|
|
18
|
+
- Text will be consumed by another agent, a translation pipeline, or a non-native English reader, and misparsing has a real cost.
|
|
19
|
+
- You are writing a prompt, system message, or tool description and want to remove ambiguity before a model ever sees it.
|
|
20
|
+
- You want a **before/after** comparison showing exactly which rule was violated and how the rewrite fixes it. Ask for it — the default output is the rewritten text alone (see Output Format).
|
|
21
|
+
|
|
22
|
+
This skill is not for creative or marketing copy — STE is deliberately flat and literal. Do not apply it to text where voice, nuance, or persuasion is the point.
|
|
23
|
+
|
|
24
|
+
## Two Modes
|
|
25
|
+
|
|
26
|
+
Pick a mode before rewriting. If the user does not say which, infer it from the text type. Keep the choice internal unless the user asks for the rule table (see Output Format).
|
|
27
|
+
|
|
28
|
+
**Strict** — procedures, error messages, tool and function descriptions, inter-agent instructions, safety text. Anywhere a wrong reading has a cost. Apply every rule below, including the hard length caps and one-word-one-meaning discipline.
|
|
29
|
+
|
|
30
|
+
**STE-flavored** — READMEs, PR descriptions, changelogs, explanatory prose. Apply the structural rules in full and treat the lexical rules as advisory (see Core Rewrite Rules for that split). In practice that means keeping the sentence length caps, active voice, simple tenses, no phrasal verbs, no semicolons, no nominalization and no marketing adjectives, while dropping the one-word-one-meaning lockdown: prose needs some range, and a strict rewrite of prose reads as a personality transplant rather than a clarification.
|
|
31
|
+
|
|
32
|
+
The two modes and the structural/lexical split are the same distinction seen from two directions. The split says which rules this skill can verify without ASD's dictionary. The modes say which of them to enforce for a given kind of text.
|
|
33
|
+
|
|
34
|
+
## Source and Scope
|
|
35
|
+
|
|
36
|
+
This skill encodes the **rule categories** of ASD-STE100 Issue 9 (Jan 2025): 53 writing rules across 9 sections covering word choice, grammar, sentence structure, and style, backed by a dictionary of ~900 approved words (one meaning, one part of speech each) and ~1,200 words to avoid with suggested replacements. See `references/writing-rules.md` for the full rule summary and citations.
|
|
37
|
+
|
|
38
|
+
It does **not** reproduce ASD's ~900-word approved dictionary verbatim. ASD-STE100 is free to obtain, but it is not free to redistribute: Issue 9, page 2 states that "no reproduction or publication of it, in whole or in part, shall be made without the written authority of an officer of ASD," and grants free reproduction rights only to eight listed categories (ASD/AIA/AIAC member associations and their member companies and customers, member-state defence ministries, A4A, airworthiness authorities, and universities and research institutes for educational purposes). This project is in none of them, so the dictionary stays out of this repo.
|
|
39
|
+
|
|
40
|
+
Instead, this skill applies the *underlying principle* (pick the plainest, most common word available and use it the same way every time) rather than checking against a fixed word list. When exact ASD-approved wording matters (e.g. actual aircraft maintenance documentation), get the standard and check word-by-word against the real dictionary. Request it from the [official downloads page](https://www.asd-ste100.org/STE_downloads.html) — note that this is a request form that emails you a link, not a direct download.
|
|
41
|
+
|
|
42
|
+
## Core Rewrite Rules
|
|
43
|
+
|
|
44
|
+
STE's rules divide into two kinds, and this skill can only fully deliver one of them. **Structural rules** are self-contained: they describe sentence shape, and you can apply them from the description alone. **Lexical rules** are defined entirely by the official ~900-word dictionary, which this skill deliberately does not reproduce (see Source and Scope). Without that dictionary, the lexical rules degrade from a checkable standard into a preference for plain words.
|
|
45
|
+
|
|
46
|
+
Apply the structural rules with confidence. Apply the lexical rules as a direction of travel, and say so in your output rather than implying dictionary compliance you cannot verify.
|
|
47
|
+
|
|
48
|
+
### Structural rules — apply these
|
|
49
|
+
|
|
50
|
+
| Rule | Do | Don't |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| Active voice | "The agent deletes the file." | "The file is deleted (by the agent)." — unless the actor is genuinely unknown or irrelevant |
|
|
53
|
+
| No phrasal verbs (Rule 9.3) | "Remove the panel." / "Start the job." | "Take off the panel." / "Spin up the job." — a two-word verb has meanings the parts do not predict |
|
|
54
|
+
| One instruction per sentence | "Open the file. Read line 3." | "Open the file and read line 3, then check if it matches." |
|
|
55
|
+
| Sentence length | ≤20 words for instructions/procedures, ≤25 words for descriptions | Long compound/subordinate-clause sentences |
|
|
56
|
+
| No semicolons (Rule 8.1) | Split into separate sentences | Any semicolon at all — STE bans the mark outright, not only as a clause join. (Rule 8.1 permits every other standard punctuation mark. The em dash is *not* banned by STE, though it often signals a sentence that should be split.) |
|
|
57
|
+
| Noun clusters | ≤3 words stacked as a noun phrase ("fuel pump valve") | 4+ word noun stacks ("high pressure fuel pump inlet valve assembly") |
|
|
58
|
+
| No ellipsis | Keep the subject, verb, and article explicit even if it reads longer | Drop words to save space ("Files not backed up will be lost" → ambiguous which files) |
|
|
59
|
+
| Keep modality | "The request **may have** failed." stays "may have" | Promote a hedge to a fact ("The request failed.") or invent a certainty the source did not state |
|
|
60
|
+
| Paragraph limits | One topic per paragraph, ≤6 sentences | Multi-topic paragraphs |
|
|
61
|
+
| Lists for sequences | Use a numbered or bulleted list for 3+ steps or conditions | Bury a sequence inside one prose sentence |
|
|
62
|
+
|
|
63
|
+
### Lexical rules — direction of travel only
|
|
64
|
+
|
|
65
|
+
| Rule | Do | Don't | Why it is weaker here |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| One word, one meaning | Pick one verb for one action and reuse it every time (e.g. always "check", never mix "check"/"verify"/"confirm" for the same action) | Rotate synonyms for the same idea across a document | Consistency within a document is checkable. Which word is the *approved* one is not, without the dictionary. |
|
|
68
|
+
| One part of speech per word | "Apply oil to the valve" (oil = noun) | "Oil the valve" (oil = verb) | Whether "oil" is approved as a noun only is a dictionary fact. Prefer the noun form when both read equally well. Do not claim compliance. |
|
|
69
|
+
| Verb, not noun (Rule 3.7) | "Analyze the log." | "Perform an analysis of the log." — a noun form of an action makes the sentence longer and hides who acts | Rule 3.7 says "use an **approved** verb to describe an action." Preferring the verb form is safe to apply anywhere. Knowing which verb is the approved one needs the dictionary. |
|
|
70
|
+
| Domain terms | Keep necessary technical nouns/verbs, but define them once if not common English (STE allows a project-specific glossary beyond its base dictionary) | Use jargon without ever defining it | The glossary allowance is real STE, but the base dictionary it extends is absent. |
|
|
71
|
+
|
|
72
|
+
### Simple tenses — apply with one exception
|
|
73
|
+
|
|
74
|
+
STE permits infinitive, imperative, simple present, simple past, simple future, and past participle as adjective. It excludes present perfect and other compound forms: "we received the report", not "we have received the report".
|
|
75
|
+
|
|
76
|
+
Aircraft manuals never need present perfect, so the exclusion costs the standard nothing. Other text is not always so lucky. "The job has completed" (and its output is available now) and "the job completed" (at some past point) are different statements, and status text frequently needs the first. **Where the compound form carries information the simple form cannot — current relevance, or a hedge as in "may have failed" — keep it and flag the departure.** Elsewhere, follow the rule.
|
|
77
|
+
|
|
78
|
+
## Scan Checklist
|
|
79
|
+
|
|
80
|
+
These six habits cover most of what makes machine-written English hard to parse. Each one is mechanical: you can point at the exact word or punctuation mark that breaks the rule, with no judgment call. Scan for all six before you rewrite anything.
|
|
81
|
+
|
|
82
|
+
1. **Synonym rotation** — the same thing gets several names in one document ("the user", "the customer", "the client"). The reader cannot tell whether they are one thing or three. Fix: pick one name, use it every time.
|
|
83
|
+
2. **Hedge stacking** — helper verbs and qualifiers pile up until the sentence asserts nothing ("it is important to note that this may potentially help to improve"). Fix: state the claim, or delete it.
|
|
84
|
+
3. **Nominalization** — an action frozen into a noun ("perform an analysis of", "provides assistance to"). Fix: use the verb ("analyze", "helps").
|
|
85
|
+
4. **Marketing adjectives** — words that claim quality instead of showing it: seamless, robust, powerful, cutting-edge, effortless, blazing-fast. Fix: delete, or replace with the measurement that earns the claim.
|
|
86
|
+
5. **Run-on sentences** — several ideas joined by semicolons or em dashes. Fix: one idea per sentence.
|
|
87
|
+
6. **Soft phrasal verbs** — spin up, reach out, dive into, kick off. Fix: use the single plain verb (start, contact, read, begin).
|
|
88
|
+
|
|
89
|
+
## Process
|
|
90
|
+
|
|
91
|
+
1. Pick the mode (Strict or STE-flavored). Say which only when the user asked for the rule table — see Output Format.
|
|
92
|
+
2. Read the input text once for meaning — do not start rewriting before you understand what it must still say afterward.
|
|
93
|
+
3. Walk it sentence by sentence. Flag every rule violation from the Core Rewrite Rules tables and every habit from the Scan Checklist. In STE-flavored mode, flag the lexical rules but do not enforce them.
|
|
94
|
+
4. Rewrite each flagged sentence to fix the violation while preserving the original meaning exactly. If a rewrite would drop necessary precision (a safety condition, a scope qualifier, a number), keep the longer phrasing and flag it instead of silently simplifying.
|
|
95
|
+
- **Check modality before you commit to a rewrite.** Hedges ("may", "could", "sometimes", "is likely to") carry the author's confidence, and confidence is content. A shorter sentence that upgrades a hedge to a fact is not a simplification — it is a different claim. This is the most common way a well-intentioned STE rewrite goes wrong, because hedges are exactly what a length cap tempts you to cut.
|
|
96
|
+
- Never add a fact the source did not state. A rewrite that reads better because it supplies a cause, a frequency, or a mechanism has stopped being a rewrite.
|
|
97
|
+
5. Output the rewritten text (see Output Format). Keep the mode choice and the rule analysis internal unless the user asked to see them.
|
|
98
|
+
6. If the input already complies, say so — do not force changes onto compliant text.
|
|
99
|
+
|
|
100
|
+
## Output Format
|
|
101
|
+
|
|
102
|
+
**Default: the rewritten text, and nothing else.** Most callers want a result they can paste straight into a tool description, an error string, or a prompt. Print the simplified text on its own. Do not add a preamble about this skill, a mode announcement, a violation count, a summary of what changed, a rule table, or a closing offer to explain further.
|
|
103
|
+
|
|
104
|
+
The one permitted addition: if step 4 kept a longer phrasing on purpose, add a single line after the text, prefixed `Kept as-is:`, naming the phrase and the precision that would have been lost. Omit the line when there is nothing to report.
|
|
105
|
+
|
|
106
|
+
**On request: the rule table.** When the user asks to see the reasoning — "show the diff", "which rules did it break", "explain the changes", "before/after" — output this table instead:
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
| Rule violated | Original | Simplified |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| Present perfect tense | "We have received your request." | "We received your request." |
|
|
112
|
+
| Noun cluster (4+ words) | "the agent task queue priority handler" | "the handler that sets task-queue priority" |
|
|
113
|
+
|
|
114
|
+
Mode: Strict. 7 violations found.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Follow the table with a one-line note on anything you deliberately did **not** simplify, and why (usually: simplifying would lose required precision).
|
|
118
|
+
|
|
119
|
+
## Boundaries
|
|
120
|
+
|
|
121
|
+
**Will:**
|
|
122
|
+
- Rewrite ambiguous or dense English into short, single-meaning, active-voice sentences.
|
|
123
|
+
- Return the rewritten text alone by default, and name the rules it applied when the user asks.
|
|
124
|
+
- Preserve every fact, condition, and scope qualifier in the original.
|
|
125
|
+
- Preserve the strength of every hedge, and add no claim the source did not make.
|
|
126
|
+
- Suggest a one-line glossary entry for domain terms that must stay.
|
|
127
|
+
|
|
128
|
+
**Will not:**
|
|
129
|
+
- Reproduce ASD's official ~900-word dictionary as if it were memorized verbatim — always treat the official download as the source of truth for exact approved wording.
|
|
130
|
+
- Simplify creative, marketing, or persuasive copy where voice and nuance are the point.
|
|
131
|
+
- Silently drop a safety condition, exception, or scope qualifier to shorten a sentence — it will flag the trade-off instead.
|
|
132
|
+
- Convert "may have failed" into "failed", or "could be caused by X" into "X is the cause" — losing a hedge changes the claim.
|
|
133
|
+
- Guarantee an aerospace/defense-grade STE-compliant document. This is a general-purpose clarity tool inspired by STE, not a certified STE authoring tool.
|
|
134
|
+
- Make weak content true or useful. STE fixes the *form* of a text, not its substance. A hollow paragraph rewritten under these rules becomes a clean, short, well-punctuated hollow paragraph. If the text has nothing to say, no rewrite fixes that — say so instead of polishing it.
|
|
135
|
+
- Shorten past the point of clarity. Cutting words is not the goal. Removing ambiguity is the goal. Past a certain point compression starts costing the reader time rather than saving it, so stop when the sentence is unambiguous, not when it is shortest.
|
|
136
|
+
|
|
137
|
+
## Additional Resources
|
|
138
|
+
|
|
139
|
+
- **`references/writing-rules.md`** — fuller summary of the 9 rule sections and dictionary structure, with citations to the official standard and secondary sources.
|
|
140
|
+
- **`examples/before-after.md`** — worked examples, including official STE examples and agent-output examples built for this skill.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Before / After Examples
|
|
2
|
+
|
|
3
|
+
## Part 1 — Official STE Examples
|
|
4
|
+
|
|
5
|
+
These illustrate real ASD-STE100 rules, drawn from public secondary sources (see `references/writing-rules.md`). They are paraphrased illustrations of the rule, not quotes from the standard itself.
|
|
6
|
+
|
|
7
|
+
| Rule | Before | After | Why |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| One meaning per word | "Verify the system." / "Check the connections." / "Confirm receipt." | "Make sure the system is correct." (one approved term used consistently) | Three near-synonyms force the reader to guess whether they mean the same action. |
|
|
10
|
+
| One part of speech per word | "Oil the valve." | "Apply oil to the valve." | If "oil" is approved only as a noun, using it as a verb breaks the one-word-one-role guarantee. |
|
|
11
|
+
| Precise verb meaning | "Follow the safety instructions." | "Obey the safety instructions." | "Follow" can mean "come after" or "obey" — STE picks the unambiguous one. |
|
|
12
|
+
| Simple tense only | "We have received the technical reports from HQ." | "We received the technical reports from HQ." | Present perfect adds a second parse ("received, and still relevant now?") that simple past avoids. |
|
|
13
|
+
| Verb, not noun | "Perform an inspection of the filter." | "Inspect the filter." | The noun form hides the action and adds a filler verb that carries no meaning. |
|
|
14
|
+
| No phrasal verbs | "Take off the access panel." | "Remove the access panel." | "Take off" also means "depart" and "deduct" — the two words together do not predict the meaning. |
|
|
15
|
+
|
|
16
|
+
## Part 2 — Applied to Agent Output
|
|
17
|
+
|
|
18
|
+
These are original examples built for this skill's actual use case: rewriting AI agent output so another agent, a translation layer, or a non-native reader can parse it without ambiguity. They are illustrations, not quotes from any real system.
|
|
19
|
+
|
|
20
|
+
Word counts below are whitespace-separated tokens (`text.split()`), punctuation not counted separately. A different tokenizer will produce a different number.
|
|
21
|
+
|
|
22
|
+
### Example A — Tool description
|
|
23
|
+
|
|
24
|
+
**Before:**
|
|
25
|
+
> This tool will attempt to synchronize state across the various backends that have been configured, and if a conflict is detected it may resolve it automatically depending on the strategy that has been set, or otherwise it will surface the conflict for manual review.
|
|
26
|
+
|
|
27
|
+
**Violations flagged:**
|
|
28
|
+
- Two instructions in one sentence (sync + resolve/surface).
|
|
29
|
+
- Present perfect in the relative clauses ("have been configured", "has been set").
|
|
30
|
+
- 44 words, far over the 25-word descriptive cap.
|
|
31
|
+
|
|
32
|
+
Note what is *not* flagged: "will attempt to" and "may resolve". Those are hedges, not violations. The tool is not promised to succeed, and the rewrite must not promise it either.
|
|
33
|
+
|
|
34
|
+
**After:**
|
|
35
|
+
> The tool tries to synchronize state across the configured backends. If it finds a conflict, it reads the configured strategy. If the strategy allows automatic resolution, the tool may resolve the conflict without a user. If the tool does not resolve the conflict, it reports the conflict for manual review.
|
|
36
|
+
|
|
37
|
+
The last sentence branches on whether the conflict was resolved, not on what the strategy allows. That is what "or otherwise" meant in the original: the fallback covers a permitted resolution that still did not happen.
|
|
38
|
+
|
|
39
|
+
### Example B — Error message
|
|
40
|
+
|
|
41
|
+
**Before:**
|
|
42
|
+
> An error may have occurred while processing your request due to a possible mismatch in the expected data format, which could be caused by an outdated client version.
|
|
43
|
+
|
|
44
|
+
**Violations flagged:**
|
|
45
|
+
- One sentence carrying three separate claims (an error occurred, a format mismatch, a client version).
|
|
46
|
+
- 28 words, over the descriptive cap.
|
|
47
|
+
|
|
48
|
+
Not flagged: "may have occurred" and "could be caused by". The message is written by a system that does not know what went wrong. Both hedges are accurate reporting of that ignorance.
|
|
49
|
+
|
|
50
|
+
**After:**
|
|
51
|
+
> Your request may have failed. The cause may be a data format that does not match what the server expects. An outdated client can cause this mismatch. Check your client version.
|
|
52
|
+
|
|
53
|
+
**This example is the reason the modality rule exists.** An earlier version of this file rewrote the first sentence as "The request failed", and the third as "an outdated client **is the most common cause**". Both read better. Both are wrong: the first asserts a failure the system only suspects, and the second invents a frequency claim that appears nowhere in the input. A rewrite that supplies a cause, a frequency, or a mechanism has stopped being a rewrite.
|
|
54
|
+
|
|
55
|
+
Note also that "may have failed" keeps a compound verb form that the simple-tense rule would otherwise remove. **When the tense rule and the modality rule conflict, modality wins** — dropping the auxiliary here would delete the uncertainty along with the tense.
|
|
56
|
+
|
|
57
|
+
### Example C — Inter-agent instruction
|
|
58
|
+
|
|
59
|
+
**Before:**
|
|
60
|
+
> Once the upstream job has completed and assuming no errors were raised, the downstream agent should proceed to consume the output artifact, though it is worth noting that partial artifacts are sometimes produced under timeout conditions.
|
|
61
|
+
|
|
62
|
+
**Violations flagged:**
|
|
63
|
+
- Present perfect ("has completed") and subordinate-clause stacking ("assuming...", "though it is worth noting...").
|
|
64
|
+
- One sentence, three separate facts (completion condition, next action, edge-case warning).
|
|
65
|
+
- 36 words, over the 20-word instruction cap.
|
|
66
|
+
|
|
67
|
+
**After:**
|
|
68
|
+
> Wait for the upstream job to finish with no errors. Then read the output artifact. Warning: a timeout can produce a partial artifact. Check that the artifact is complete before you use it.
|
|
69
|
+
|
|
70
|
+
Two deliberate calls worth stating rather than hiding:
|
|
71
|
+
- "should proceed to consume" became the imperative "read". STE permits this for instructions, where a recommendation addressed to the executing agent is a command. Do not make the same move in descriptive text.
|
|
72
|
+
- The final sentence is **new**. The original warned about partial artifacts without saying what to do about it. Adding the check makes the warning actionable, but it is added content, so it is called out here rather than passed off as a rewrite. If the source's silence was deliberate, drop the sentence.
|
|
73
|
+
|
|
74
|
+
### Example D — README prose (STE-flavored mode)
|
|
75
|
+
|
|
76
|
+
**Before:**
|
|
77
|
+
> Our caching layer is designed to slot seamlessly into your existing stack with minimal friction and no vendor lock-in; it leverages semantic similarity to dramatically reduce the cache misses that traditionally plague LLM workloads.
|
|
78
|
+
|
|
79
|
+
**Violations flagged:**
|
|
80
|
+
- Marketing adjectives and claims without measurement ("seamlessly", "minimal friction", "dramatically").
|
|
81
|
+
- Semicolon joining two separate ideas.
|
|
82
|
+
- Nominalization and soft phrasing ("is designed to slot into", "leverages").
|
|
83
|
+
- 34 words, over the 25-word descriptive cap.
|
|
84
|
+
|
|
85
|
+
**After:**
|
|
86
|
+
> A normal cache matches requests by exact text, so a small change in wording causes a cache miss. This cache compares the meaning of a new prompt against the prompts it already holds. It runs alongside your current stack and stores no data outside it.
|
|
87
|
+
|
|
88
|
+
Flavored mode kept the explanatory rhythm and did not force one fixed term per concept. It still cut the marketing adjectives, the semicolon, and the length.
|
|
89
|
+
|
|
90
|
+
## How to Read These Examples
|
|
91
|
+
|
|
92
|
+
Part 1 shows the actual rules this skill is built on. Part 2 shows the transfer: the same discipline — one meaning per word, active voice, simple tense, one instruction per sentence, explicit conditions instead of buried subordinate clauses — makes machine-to-machine and cross-language text safer to parse, not just aircraft manuals.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ASD-STE100 Writing Rules — Summary and Sources
|
|
2
|
+
|
|
3
|
+
This file summarizes the public, official description of ASD-STE100 (Simplified Technical English). It paraphrases rule *categories*. It does not reproduce the standard's text or its ~900-word dictionary verbatim. For the authoritative document, request the free download at the official site.
|
|
4
|
+
|
|
5
|
+
## What ASD-STE100 Is
|
|
6
|
+
|
|
7
|
+
ASD-STE100 is a controlled natural language, first released in 1986 (as AECMA Document PSC-85-16598) by what is now ASD (the AeroSpace and Defense Industries Association of Europe). It was built at the request of European airlines — most staffed by non-native English speakers — who needed maintenance documentation that could not be misread, because a misread instruction on an aircraft can kill people. The standard is maintained by the Simplified Technical English Maintenance Group (STEMG) and has been free to download since Issue 6 (2013). The current edition is Issue 9 (January 2025).
|
|
8
|
+
|
|
9
|
+
## Structure
|
|
10
|
+
|
|
11
|
+
- **53 writing rules across 9 sections** covering word choice, grammar, sentence structure, and style.
|
|
12
|
+
- **A dictionary** of roughly 900 approved words, each restricted to one meaning and one part of speech, plus roughly 1,200 words to avoid with suggested replacements.
|
|
13
|
+
- **A terminology allowance**: organizations may define their own dictionary of approved technical nouns and verbs beyond the base ~900 words, for domain-specific vocabulary the base dictionary can't cover.
|
|
14
|
+
|
|
15
|
+
## Rule Categories (Paraphrased)
|
|
16
|
+
|
|
17
|
+
**Word choice**
|
|
18
|
+
- Use approved words only in their approved meaning and part of speech.
|
|
19
|
+
- Each word maps to exactly one meaning — don't rely on context to disambiguate a word that has several dictionary senses.
|
|
20
|
+
- Prefer the plainer, shorter, more common word over a formal or rare synonym.
|
|
21
|
+
- Use an approved verb for an action, not a noun derived from that verb (Rule 3.7).
|
|
22
|
+
- Do not make phrasal verbs by putting a verb and a preposition together (Rule 9.3). Their meaning is not predictable from the parts, and non-native readers and translation systems both mishandle them.
|
|
23
|
+
|
|
24
|
+
**Verb forms**
|
|
25
|
+
- Permitted forms: infinitive, imperative, simple present, simple past, simple future, and past participle used only as an adjective.
|
|
26
|
+
- No present perfect, past perfect, or other compound/auxiliary constructions. "We have received" is not allowed. "We received" is allowed.
|
|
27
|
+
- "-ing" forms are permitted only as a technical noun or as part of a technical noun, not as a verb form.
|
|
28
|
+
|
|
29
|
+
**Voice**
|
|
30
|
+
- Active voice is required for procedures and instructions.
|
|
31
|
+
- Passive voice is allowed only in descriptive text, and only when the actor performing the action is genuinely unknown or irrelevant to the reader.
|
|
32
|
+
|
|
33
|
+
**Sentence structure**
|
|
34
|
+
- One instruction per sentence.
|
|
35
|
+
- Maximum ~20 words per sentence for procedures and instructions. Maximum ~25 words for descriptive text.
|
|
36
|
+
- Do not omit sentence parts (verb, subject, article) just to shorten the sentence — the standard explicitly warns that this creates ambiguity rather than clarity.
|
|
37
|
+
- Noun clusters (strings of nouns stacked as a modifier) are capped at 3 words.
|
|
38
|
+
- Semicolons are not permitted at all (Rule 8.1): "You can use all standard English punctuation marks but not the semicolon (;)." Write separate sentences instead. Every other standard mark, including the em dash, remains permitted.
|
|
39
|
+
|
|
40
|
+
**Paragraph and document structure**
|
|
41
|
+
- One topic per paragraph.
|
|
42
|
+
- Maximum ~6 sentences per paragraph.
|
|
43
|
+
- Use vertical (numbered or bulleted) lists for sequences, conditions, or complex enumerations instead of burying them in prose.
|
|
44
|
+
|
|
45
|
+
**Safety instructions**
|
|
46
|
+
- Safety-critical instructions must open with a clear command or condition, not be buried mid-sentence.
|
|
47
|
+
|
|
48
|
+
## Why This Skill Repurposes STE for Agent Output
|
|
49
|
+
|
|
50
|
+
STE was designed to eliminate ambiguity for a reader who cannot ask a follow-up question — a technician on a tarmac, working from a manual, with no author to call. An AI agent parsing another agent's output, a tool description, or a system message is in the same position: no back-channel to resolve "does this passive-voice sentence mean the caller does X, or the callee does X?" The same rule set that protects an airline mechanic from a misread torque spec protects a downstream agent from a misread instruction.
|
|
51
|
+
|
|
52
|
+
## Sources
|
|
53
|
+
|
|
54
|
+
- [ASD-STE100 official site](https://www.asd-ste100.org/)
|
|
55
|
+
- [ASD-STE100 — About STE](https://www.asd-ste100.org/about_STE.html)
|
|
56
|
+
- [ASD Europe — Simplified Technical English](https://www.asd-europe.org/standards-specifications/simplified-technical-english/)
|
|
57
|
+
- [Simplified Technical English — Wikipedia](https://en.wikipedia.org/wiki/Simplified_Technical_English)
|
|
58
|
+
- [TechScribe — ASD-STE100 Simplified Technical English](https://www.techscribe.co.uk/techw/asd-simplified-technical-english.htm)
|
|
59
|
+
- [SKYbrary — Simplified Technical English (STE)](https://skybrary.aero/articles/simplified-technical-english-ste)
|