@orchestraworks/cli 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/api/compute-provider-check.d.ts +29 -0
- package/dist/cli/api/compute-provider-check.js +207 -0
- package/dist/cli/api/tail.d.ts +66 -0
- package/dist/cli/api/tail.js +564 -0
- package/dist/cli/main.d.ts +5 -1
- package/dist/cli/main.js +22 -0
- package/dist/constructs/agent.d.ts +10 -0
- package/dist/constructs/agent.js +39 -4
- package/dist/constructs/environment.d.ts +29 -1
- package/dist/constructs/environment.js +28 -1
- package/dist/constructs/skill.d.ts +6 -1
- package/dist/constructs/skill.js +21 -2
- package/dist/engine/reconcile.js +15 -1
- package/dist/generated/cli-commands.json +842 -0
- package/dist/generated/managed-skills.d.ts +2 -0
- package/dist/generated/managed-skills.js +13 -0
- package/dist/index.d.ts +1 -1
- package/docs/REFERENCE.md +21 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/ComputeProvider.d.ts +3 -3
- package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/Environment.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/Environment.js +5 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHook.d.ts +38 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHook.js +45 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooks.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooks.js +44 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooksRequest.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooksRequest.js +44 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpec.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpecRequest.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.d.ts +19 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.js +7 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/Machine.d.ts +7 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/Machine.js +2 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/index.d.ts +3 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/index.js +3 -0
- package/node_modules/@orchestraworks/client/dist/models/ComputeProvider.d.ts +3 -3
- package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/models/Environment.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/models/Environment.js +5 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHook.d.ts +38 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHook.js +52 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooks.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooks.js +51 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooksRequest.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooksRequest.js +51 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpec.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpecRequest.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.d.ts +19 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.js +7 -0
- package/node_modules/@orchestraworks/client/dist/models/Machine.d.ts +7 -1
- package/node_modules/@orchestraworks/client/dist/models/Machine.js +2 -0
- package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/models/index.d.ts +3 -0
- package/node_modules/@orchestraworks/client/dist/models/index.js +3 -0
- package/node_modules/@orchestraworks/client/package.json +1 -1
- package/package.json +4 -4
- package/skills/orchestra/SKILL.md +167 -42
- package/skills/orchestra-fdk/SKILL.md +112 -545
- package/skills/orchestra-fdk/references/authoring.md +29 -2
- package/skills/orchestra-fdk/references/environment.md +295 -41
- package/skills/orchestra-fdk/references/integrations/analytics.md +18 -0
- package/skills/orchestra-fdk/references/integrations/ci-cd.md +20 -0
- package/skills/orchestra-fdk/references/integrations/cloud.md +19 -0
- package/skills/orchestra-fdk/references/integrations/code-repo.md +76 -0
- package/skills/orchestra-fdk/references/integrations/databases.md +22 -0
- package/skills/orchestra-fdk/references/integrations/dependencies.md +29 -0
- package/skills/orchestra-fdk/references/integrations/design.md +18 -0
- package/skills/orchestra-fdk/references/integrations/feature-flags.md +19 -0
- package/skills/orchestra-fdk/references/integrations/incident.md +29 -0
- package/skills/orchestra-fdk/references/integrations/issue-tracker.md +65 -0
- package/skills/orchestra-fdk/references/integrations/knowledge-base.md +43 -0
- package/skills/orchestra-fdk/references/integrations/messaging.md +38 -0
- package/skills/orchestra-fdk/references/integrations/observability.md +36 -0
- package/skills/orchestra-fdk/references/integrations/secrets-managers.md +25 -0
- package/skills/orchestra-fdk/references/integrations/support-desk.md +31 -0
- package/skills/orchestra-fdk/references/phases/0-start.md +62 -0
- package/skills/orchestra-fdk/references/phases/1-discover.md +111 -0
- package/skills/orchestra-fdk/references/phases/2-plan.md +157 -0
- package/skills/orchestra-fdk/references/phases/3-connect.md +99 -0
- package/skills/orchestra-fdk/references/phases/4-build.md +159 -0
- package/skills/orchestra-fdk/references/phases/5-prove.md +107 -0
- package/skills/orchestra-fdk/references/phases/6-handover.md +42 -0
- package/skills/orchestra-fdk/references/troubleshooting.md +128 -0
- package/templates/bug-fix/agents/bugfix.md +1 -1
- package/templates/bug-fix/main.ts +1 -1
- package/templates/engineering-team/README.md +45 -181
- package/templates/engineering-team/agents/engineer-agent.md +10 -7
- package/templates/engineering-team/agents/manager-agent.md +23 -120
- package/templates/engineering-team/inputs.json +1 -3
- package/templates/engineering-team/lib/environment.ts +10 -90
- package/templates/engineering-team/lib/inputs.ts +5 -97
- package/templates/engineering-team/main.ts +22 -69
- package/templates/todo-factory/agents/bugfix.md +1 -1
- package/templates/todo-factory/main.ts +1 -1
- package/templates/engineering-team/agents/engineer-bare.md +0 -22
- package/templates/engineering-team/onboarding/create-score-metrics.sh +0 -33
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
## Attribution
|
|
2
|
+
You are Manager Agent. Mark the work you produce as yours:
|
|
3
|
+
- every commit message and pull request description ends with
|
|
4
|
+
Co-Authored-By: Manager Agent <manager-agent@agents.orchestraworks.ai>
|
|
5
|
+
- every comment and tracker edit ends with one line: — Manager Agent, Orchestra
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
You are the Manager Agent. You run this team's software factory. A person assigns you items in the Bugs,
|
|
8
|
+
Features and Support pipelines, one item per conversation. The item is your first message. You triage it, give
|
|
9
|
+
it the code, and assign it to an Engineer Agent. An item's review stage is In review in Bugs and Features, and
|
|
10
|
+
Waiting on requester in Support.
|
|
5
11
|
|
|
6
|
-
The
|
|
7
|
-
that holds a repository's history:
|
|
12
|
+
<repository-notes> The `orchestra` command on this machine reaches the platform as you.
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
You give the Engineer Agents the code as a git bundle, a single file that holds a repository's history. The
|
|
15
|
+
bundle fixes the commit the work starts from, so the author and the reviewer of a change read the same code:
|
|
16
|
+
|
|
17
|
+
1. Clone the repository under `/work`, the machine's large disk. The work starts from the commit at the tip
|
|
18
|
+
of <branch>.
|
|
19
|
+
2. Make a branch at that commit and bundle only it: `git branch work <commit>` then
|
|
12
20
|
`git bundle create work.bundle work`. Check it with `git bundle verify work.bundle`.
|
|
13
21
|
3. Upload it as a File:
|
|
14
22
|
`orchestra files create --file work.bundle --filename work.bundle --content-type application/octet-stream --output json`.
|
|
@@ -16,105 +24,6 @@ that holds a repository's history:
|
|
|
16
24
|
4. Put the File id in the item's description, as a line `Code bundle: <file id>`, with the issue text the
|
|
17
25
|
Engineer Agent may read.
|
|
18
26
|
|
|
19
|
-
The items you work on:
|
|
20
|
-
|
|
21
|
-
- Set up. Clone the repository, install it, build it, run its tests, and start the app. The tests must give
|
|
22
|
-
the same result as the team's CI. Report each command, its result and how long it took. Then cut a
|
|
23
|
-
bundle of <branch> and prove an Engineer Agent can run the tests from it.
|
|
24
|
-
- Bootstrap. Teach the Engineer Agents this codebase from its past pull requests, then test them on pull
|
|
25
|
-
requests they have not seen. The item's description gives the threshold. A Bootstrap has at most 2 rounds.
|
|
26
|
-
Keep the state as comments on the Bootstrap item: the round, the cut date, the skill and the Replay item
|
|
27
|
-
ids. A new conversation on this item reads them to know where the work stands.
|
|
28
|
-
1. Choose a cut date T. The test set is 10 recent merged pull requests after T, mixing about 5 bug fixes
|
|
29
|
-
and 5 features. The study set is the 50 merged pull requests just before T, also bugs and features.
|
|
30
|
-
Choose the test set from titles and issue types only. Do not open a test pull request's diff before you
|
|
31
|
-
score it.
|
|
32
|
-
2. Study. Read the code and its history only as they were at T: <branch> already holds the 10 test
|
|
33
|
-
changes, so anything later would teach their fixes. Make a study copy that holds nothing after T. In
|
|
34
|
-
your clone, run `git rev-list -1 --first-parent --before=<T> origin/HEAD` to find the commit at T,
|
|
35
|
-
then `git branch study <commit at T>`, `git bundle create study.bundle study` and
|
|
36
|
-
`git clone --branch study study.bundle /work/study`. Read the code and `git log` only in `/work/study`,
|
|
37
|
-
never in your clone or on <branch> past T. Read the 50 there, and write a direction map. Skip `AGENTS.md`
|
|
38
|
-
and `CLAUDE.md`, because the harness already loads them. The map holds:
|
|
39
|
-
- implicit rules: what the team always does but never wrote down;
|
|
40
|
-
- hidden connections: files that change together, and invariants across layers;
|
|
41
|
-
- the bug and feature map: where each kind of bug and feature lives, and how the team fixed or built it;
|
|
42
|
-
- directions: work in motion, and which patterns are old and which are new;
|
|
43
|
-
- where to look first, for each kind of work.
|
|
44
|
-
Each entry cites two or more commits or files. Label an entry that rests on one example as a guess.
|
|
45
|
-
3. Apply. Write the map into the Engineer Agents' codebase skill as one new version, as "Where knowledge
|
|
46
|
-
goes" says.
|
|
47
|
-
4. Test. For each of the 10, create a Replay item in this Onboarding pipeline, with the issue text and a
|
|
48
|
-
bundle cut at the commit before the fix, and assign it to engineer-lg. When its report is ready, or when
|
|
49
|
-
it is stuck, the Engineer Agent assigns the item back to you, which starts a new conversation that
|
|
50
|
-
scores it. These are the full replays: the agent with the codebase skill and its work loop.
|
|
51
|
-
5. Baseline. At the same time as step 4, create a second Replay item for each of the same 10, and assign it
|
|
52
|
-
to engineer-bare. Its description holds only the raw ticket text and the `Code bundle:` line: no triage
|
|
53
|
-
notes and no hints. engineer-bare has no codebase skill and no work loop in its instructions, so its
|
|
54
|
-
replays measure what the study adds. Start each title with `Baseline:`. Score these the same way, with
|
|
55
|
-
the same rule.
|
|
56
|
-
6. Calibrate. When the last replay of the round is scored, its scoring conversation assigns the Bootstrap
|
|
57
|
-
item back to you, and this same Bootstrap conversation resumes. It knows the first scores, so it does not
|
|
58
|
-
re-score. Create a separate item titled `Calibrate, round <N>` in this Onboarding pipeline, whose
|
|
59
|
-
description names the Bootstrap item and 3 of the 10 full Replay items, and assign it to `manager-agent`.
|
|
60
|
-
A new item starts a new conversation. Then stop and wait.
|
|
61
|
-
When the Calibrate conversation assigns the Bootstrap item back to you, go on with step 7.
|
|
62
|
-
7. Check the threshold, on the 10 full replays only, with the scores Calibrate kept. Then write one comment
|
|
63
|
-
on the Bootstrap item that puts the two sets side by side: for `arm=full` and for `arm=bare`, the
|
|
64
|
-
replays that pass of the 10, and the mean F0.5, precision, raw precision and recall. The baseline is
|
|
65
|
-
reported and gates nothing. On a pass, move the Bootstrap item to Done, and write that the factory is
|
|
66
|
-
ready to commission, naming the codebase skill's slug.
|
|
67
|
-
8. On a fail, write what the Engineer Agents were missing, as kinds of knowledge. Fix the skill as a new
|
|
68
|
-
version, from the study set and `/work/study` only. Do not write a test item's real fix into it, or
|
|
69
|
-
anything that only that fix would teach. Then start round 2 with the same T and a fresh 10, bugs and
|
|
70
|
-
features, from the merged pull requests after T that round 1 did not use. The study copy ends at T, so
|
|
71
|
-
neither the skill nor this conversation has seen them. Choose them as step 1 says, from titles and issue
|
|
72
|
-
types only. If fewer than 10 remain, use all that remain, and write how many on the Bootstrap item.
|
|
73
|
-
Round 2 runs its own Baseline on its 10. Stop after round 2: if it fails too, move the Bootstrap item to
|
|
74
|
-
Needs review and say what is missing.
|
|
75
|
-
- Score a replay in the conversation its Replay item starts when it comes back to you. If the Engineer
|
|
76
|
-
Agent is stuck, give it what it needs and assign the item back to it, or score what it has. To score,
|
|
77
|
-
apply the Engineer Agent's patch to the commit before the fix, and run the real pull request's tests on
|
|
78
|
-
it. Then compare the change with the real one:
|
|
79
|
-
- A change is wrong when it breaks behavior, or does something the issue does not ask for.
|
|
80
|
-
- The work loop adds tests and doc comments the real fix may not have. Count each such added test or doc
|
|
81
|
-
comment as neutral: it is not a match and not a mismatch, so it changes neither precision nor recall.
|
|
82
|
-
- Precision is the agent's changes that match the real fix, divided by all the agent's changes that are not
|
|
83
|
-
neutral. Recall is the real fix's changes the agent made, divided by all the real fix's changes.
|
|
84
|
-
F0.5 = 1.25 × precision × recall ÷ (0.25 × precision + recall). It is 0 when the agent made no change,
|
|
85
|
-
or when either is 0.
|
|
86
|
-
- Raw precision is the agent's changes that match the real fix, divided by all the agent's changes, the
|
|
87
|
-
neutral ones included. Record it too. It does not enter F0.5.
|
|
88
|
-
- For a feature, judge whether the change does what the ticket asks.
|
|
89
|
-
- The replay passes when no change is wrong, the real pull request's tests pass on it, and a feature does
|
|
90
|
-
what the ticket asks. A failed replay gives its F0.5 and counts too.
|
|
91
|
-
Write the scores as metric values on the Replay item, with numbers to two decimals. Each value carries the
|
|
92
|
-
label `arm`: `full` for an engineer-lg replay, `bare` for an engineer-bare replay. The write command has no
|
|
93
|
-
flag for the subject or the labels, so write them to a file once per item, for example `score.json`:
|
|
94
|
-
```
|
|
95
|
-
{"subject":{"kind":"workItem","id":"<item id>"},"labels":{"arm":"full"}}
|
|
96
|
-
```
|
|
97
|
-
Then write each value with it:
|
|
98
|
-
```
|
|
99
|
-
orchestra metrics write-value replay-pass --value true --body score.json
|
|
100
|
-
orchestra metrics write-value replay-f05 --value 0.83 --body score.json
|
|
101
|
-
orchestra metrics write-value replay-precision --value 0.83 --body score.json
|
|
102
|
-
orchestra metrics write-value replay-raw-precision --value 0.71 --body score.json
|
|
103
|
-
orchestra metrics write-value replay-recall --value 1 --body score.json
|
|
104
|
-
```
|
|
105
|
-
Then add one comment with `orchestra work-items create-activity <item id> --text <comment>`: each wrong change,
|
|
106
|
-
each change you counted as neutral, the real pull request's tests that pass of all of them, and for a
|
|
107
|
-
feature your judgment and its reason.
|
|
108
|
-
Do not write the score as a check: your role cannot write checks. Move the Replay item to Done. If every
|
|
109
|
-
Replay item of the round is now Done, assign the Bootstrap item to `manager-agent`.
|
|
110
|
-
- Calibrate. In this conversation, re-score each of the 3 replays from the start, as "Score a replay" says,
|
|
111
|
-
but write no metric value. Read a replay's first scores only after you write yours. Add one comment on the
|
|
112
|
-
Bootstrap item with your scores, each disagreement, and which score you keep. Move the Calibrate item to
|
|
113
|
-
Done, then assign the Bootstrap item to `manager-agent`, which resumes the Bootstrap conversation at its
|
|
114
|
-
step 7.
|
|
115
|
-
|
|
116
|
-
After commissioning, the team improves the agents from real work, measured with these metrics.
|
|
117
|
-
|
|
118
27
|
Where knowledge goes:
|
|
119
28
|
|
|
120
29
|
- Your instructions and the Engineer Agents' instructions hold role, limits, when to ask a person, and how
|
|
@@ -129,16 +38,15 @@ Where knowledge goes:
|
|
|
129
38
|
{"slug":"codebase-1","files":[{"path":"SKILL.md","fileId":"<file id>"}]}
|
|
130
39
|
```
|
|
131
40
|
Create the skill with `orchestra skills create --body skill.json --output json`, and note its `id`. Point
|
|
132
|
-
engineer-sm, engineer-md and engineer-lg at it, by name
|
|
133
|
-
|
|
134
|
-
already has:
|
|
41
|
+
engineer-sm, engineer-md and engineer-lg at it, by name. For each of the three, write `agent-skills.json`,
|
|
42
|
+
keeping any skill id the agent already has:
|
|
135
43
|
```
|
|
136
44
|
{"skillIds":["<skill id>"]}
|
|
137
45
|
```
|
|
138
46
|
Then run `orchestra agents update <agent slug> --body agent-skills.json`, with `engineer-sm`, `engineer-md` and
|
|
139
47
|
`engineer-lg` as the slug. That makes one new agent version of each.
|
|
140
48
|
- An agent version records which skills an agent uses, not their text. So a new version of the skill is a
|
|
141
|
-
new skill, `codebase-2`, and engineer-sm, engineer-md and engineer-lg point at it.
|
|
49
|
+
new skill, `codebase-2`, and engineer-sm, engineer-md and engineer-lg point at it.
|
|
142
50
|
- An `orchestra fdk apply` sets the Engineer Agents back to the code, which names no skill until a person adds it.
|
|
143
51
|
Name the skill's slug when you report, so the person can add it.
|
|
144
52
|
- Hand the codebase skill to the team as a pull request that adds it to `.agents/skills/`, when an item
|
|
@@ -147,16 +55,11 @@ Where knowledge goes:
|
|
|
147
55
|
|
|
148
56
|
Rules:
|
|
149
57
|
|
|
150
|
-
-
|
|
151
|
-
included. Until every test item of a round is scored, never write the real fix of any of them, or anything
|
|
152
|
-
that tells its specifics, into an item, a comment, a File, a skill or the Bootstrap conversation. In the
|
|
153
|
-
Bootstrap conversation, name only the issue, its pull request's number and the commit before the fix.
|
|
154
|
-
Read a real fix only in the conversation that scores its replay.
|
|
155
|
-
- When you need a person, move the item to Needs review and say exactly what you need.
|
|
58
|
+
- When you need a person, move the item to its review stage and say exactly what you need.
|
|
156
59
|
- Triage each work item before you assign it. Look for a requirement that narrows or conflicts with what the
|
|
157
60
|
code does today. When you find one, write the question on the item before you assign it.
|
|
158
|
-
- Work goes to engineer-lg first. Do not send work to engineer-sm or engineer-md until
|
|
159
|
-
kind
|
|
160
|
-
|
|
61
|
+
- Work goes to engineer-lg first. Do not send work to engineer-sm or engineer-md until a person says that a
|
|
62
|
+
kind of work may go to them. engineer-lg assigns its changes to engineer-md for review: that is not work you
|
|
63
|
+
send.
|
|
161
64
|
- Never push to <branch>. Push a branch and open a pull request only when an item asks for one.
|
|
162
65
|
- Stop any Monitor or background task you started before your final message.
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
// The machines the agents work on, and the keys they use. main.ts declares all of them.
|
|
2
2
|
//
|
|
3
3
|
// An environment declared in code keeps only what it declares: `orchestra fdk apply` removes every rule and setting
|
|
4
|
-
// added by hand or by the platform at create. So the model gateway rule
|
|
5
|
-
//
|
|
4
|
+
// added by hand or by the platform at create. So the model gateway rule is declared here, on every environment,
|
|
5
|
+
// and nothing else is assumed.
|
|
6
6
|
//
|
|
7
7
|
// Following the orchestra-fdk skill's environment reference, an agent edits the section marked WHAT THE CODE
|
|
8
8
|
// NEEDS once it has found how the team's code is installed, tested and started.
|
|
9
9
|
|
|
10
10
|
import { readFileSync } from "node:fs";
|
|
11
|
-
import {
|
|
12
|
-
EgressPolicy,
|
|
13
|
-
Environment,
|
|
14
|
-
GatewayKey,
|
|
15
|
-
Secret,
|
|
16
|
-
SecretValue,
|
|
17
|
-
basic,
|
|
18
|
-
bearer,
|
|
19
|
-
type Factory,
|
|
20
|
-
type ISecret,
|
|
21
|
-
} from "@orchestraworks/cli";
|
|
22
|
-
import { TOKEN_VARIABLES, type Connected, type Inputs } from "./inputs.js";
|
|
11
|
+
import { EgressPolicy, Environment, GatewayKey, Secret, SecretValue, type Factory, type ISecret } from "@orchestraworks/cli";
|
|
23
12
|
|
|
24
13
|
/** A size is the machine: 2, 16 or 32 CPU, with 2 GB of memory per CPU. */
|
|
25
14
|
export type Size = "sm" | "md" | "lg";
|
|
@@ -45,15 +34,13 @@ const PORTS: { name: string; port: number }[] = [];
|
|
|
45
34
|
|
|
46
35
|
// ---- END OF WHAT THE CODE NEEDS ----------------------------------------------------------------------------
|
|
47
36
|
|
|
48
|
-
/** The secrets the working environments use.
|
|
37
|
+
/** The secrets the working environments use. */
|
|
49
38
|
export interface Keys {
|
|
50
39
|
modelGateway: ISecret;
|
|
51
|
-
bitbucket?: { api: ISecret; git: ISecret };
|
|
52
|
-
jira?: ISecret;
|
|
53
40
|
}
|
|
54
41
|
|
|
55
|
-
/** Declares the one model gateway key
|
|
56
|
-
export function declareKeys(factory: Factory
|
|
42
|
+
/** Declares the one model gateway key. */
|
|
43
|
+
export function declareKeys(factory: Factory): Keys {
|
|
57
44
|
const gatewayKey = new GatewayKey(factory, "model-gateway", {
|
|
58
45
|
slug: "model-gateway",
|
|
59
46
|
displayName: "Factory agents",
|
|
@@ -64,74 +51,7 @@ export function declareKeys(factory: Factory, inputs: Inputs, connected: Connect
|
|
|
64
51
|
description: "Added to model calls at the network edge. The agents never see it.",
|
|
65
52
|
value: SecretValue.fromGatewayKey(gatewayKey),
|
|
66
53
|
});
|
|
67
|
-
|
|
68
|
-
if (connected.bitbucket) {
|
|
69
|
-
// Bitbucket takes an API token as a Bearer header on its REST API, and as Basic auth with the fixed
|
|
70
|
-
// user name x-bitbucket-api-token-auth for git over HTTPS (support.atlassian.com, "Using API tokens").
|
|
71
|
-
keys.bitbucket = {
|
|
72
|
-
api: new Secret(factory, "bitbucket-api-token", {
|
|
73
|
-
slug: "bitbucket-api-token",
|
|
74
|
-
name: "Bitbucket API token",
|
|
75
|
-
value: SecretValue.fromEnv(TOKEN_VARIABLES.bitbucket),
|
|
76
|
-
}),
|
|
77
|
-
git: new Secret(factory, "bitbucket-git-token", {
|
|
78
|
-
slug: "bitbucket-git-token",
|
|
79
|
-
name: "Bitbucket token for git",
|
|
80
|
-
value: SecretValue.basicAuth("x-bitbucket-api-token-auth", SecretValue.fromEnv(TOKEN_VARIABLES.bitbucket)),
|
|
81
|
-
}),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
if (connected.jira) {
|
|
85
|
-
// Jira takes an API token as Basic auth over the account email and the token. The secret holds
|
|
86
|
-
// base64("<email>:<token>"), formed at apply.
|
|
87
|
-
keys.jira = new Secret(factory, "jira-token", {
|
|
88
|
-
slug: "jira-token",
|
|
89
|
-
name: "Jira API token",
|
|
90
|
-
value: SecretValue.basicAuth(inputs.jiraEmail, SecretValue.fromEnv(TOKEN_VARIABLES.jira)),
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
return keys;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* What an environment's agents may do on Bitbucket and Jira.
|
|
98
|
-
* - `tokens`: the edge adds each connected token on its hosts. The Manager Agent works here.
|
|
99
|
-
* - `blocked`: the Bitbucket hosts are denied, and the Jira site once it is set. The Engineer Agents work here until commissioning, and get their
|
|
100
|
-
* code as a git bundle the Manager Agent uploads. At commissioning, switch them to `tokens`. The edge reads
|
|
101
|
-
* these rules live, so the change reaches running machines too: apply it only when no replay is running.
|
|
102
|
-
*/
|
|
103
|
-
export type TrackerAccess = "tokens" | "blocked";
|
|
104
|
-
|
|
105
|
-
/** Open to every host, as the first run needs, with the model gateway key added on the gateway's host. */
|
|
106
|
-
function egress(keys: Keys, inputs: Inputs, access: TrackerAccess): EgressPolicy {
|
|
107
|
-
const policy = EgressPolicy.allowAll().routeModelsViaGateway({ key: keys.modelGateway });
|
|
108
|
-
if (access === "blocked") {
|
|
109
|
-
// A deny defaults to priority 900, above every allow rule, so these hosts stay closed under allowAll().
|
|
110
|
-
const denied = policy.deny("bitbucket", { hosts: ["bitbucket.org", "api.bitbucket.org"] });
|
|
111
|
-
return inputs.jiraSite === "" ? denied : denied.deny("jira", { hosts: [inputs.jiraSite] });
|
|
112
|
-
}
|
|
113
|
-
let tokens = policy;
|
|
114
|
-
if (keys.bitbucket !== undefined) {
|
|
115
|
-
tokens = tokens
|
|
116
|
-
.allow("bitbucket-api", {
|
|
117
|
-
hosts: ["api.bitbucket.org"],
|
|
118
|
-
priority: 300,
|
|
119
|
-
credential: bearer("Authorization", keys.bitbucket.api),
|
|
120
|
-
})
|
|
121
|
-
.allow("bitbucket-git", {
|
|
122
|
-
hosts: ["bitbucket.org"],
|
|
123
|
-
priority: 300,
|
|
124
|
-
credential: basic("Authorization", keys.bitbucket.git),
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
if (keys.jira !== undefined) {
|
|
128
|
-
tokens = tokens.allow("jira", {
|
|
129
|
-
hosts: [inputs.jiraSite],
|
|
130
|
-
priority: 300,
|
|
131
|
-
credential: basic("Authorization", keys.jira),
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
return tokens;
|
|
54
|
+
return { modelGateway };
|
|
135
55
|
}
|
|
136
56
|
|
|
137
57
|
/** One working environment. Every agent runs on one of these. */
|
|
@@ -140,8 +60,7 @@ export function declareEnvironment(
|
|
|
140
60
|
id: string,
|
|
141
61
|
size: Size,
|
|
142
62
|
keys: Keys,
|
|
143
|
-
|
|
144
|
-
options: { access: TrackerAccess; codex?: boolean },
|
|
63
|
+
options: { codex?: boolean } = {},
|
|
145
64
|
): Environment {
|
|
146
65
|
return new Environment(factory, id, {
|
|
147
66
|
slug: id,
|
|
@@ -159,6 +78,7 @@ export function declareEnvironment(
|
|
|
159
78
|
{ mountPath: "/work", size: WORK_DISK_SIZE },
|
|
160
79
|
],
|
|
161
80
|
ingress: PORTS.map((port) => ({ ...port, access: "authenticated" as const })),
|
|
162
|
-
|
|
81
|
+
// Open to every host, with the model gateway key added on the gateway's host.
|
|
82
|
+
egress: EgressPolicy.allowAll().routeModelsViaGateway({ key: keys.modelGateway }),
|
|
163
83
|
});
|
|
164
84
|
}
|
|
@@ -1,117 +1,25 @@
|
|
|
1
1
|
// The values this factory needs from the team. The setup skill writes them into inputs.json.
|
|
2
|
-
// The two tokens are not here: `orchestra fdk apply` reads them from the shell, so no file ever holds them.
|
|
3
2
|
//
|
|
4
|
-
// Every value may be empty.
|
|
5
|
-
//
|
|
3
|
+
// Every value may be empty. Any git host works: the Manager Agent clones the repository to cut the bundle the
|
|
4
|
+
// Engineer Agents work from, and this factory declares no code host or tracker token.
|
|
6
5
|
|
|
7
6
|
import { readFileSync } from "node:fs";
|
|
8
|
-
import { Construct, type Factory } from "@orchestraworks/cli";
|
|
9
7
|
|
|
10
8
|
export interface Inputs {
|
|
11
|
-
/** The
|
|
9
|
+
/** The address `git clone` takes, such as https://github.com/acme/shop.git. */
|
|
12
10
|
repositoryUrl: string;
|
|
13
11
|
/** The branch pull requests go to, such as main. */
|
|
14
12
|
repositoryDefaultBranch: string;
|
|
15
|
-
/** The Jira site host, such as acme.atlassian.net. */
|
|
16
|
-
jiraSite: string;
|
|
17
|
-
/** The Atlassian account email the Jira token belongs to. */
|
|
18
|
-
jiraEmail: string;
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
export const TOKEN_VARIABLES = {
|
|
23
|
-
bitbucket: "ORCHESTRA_FDK_BITBUCKET_TOKEN",
|
|
24
|
-
jira: "ORCHESTRA_FDK_JIRA_TOKEN",
|
|
25
|
-
} as const;
|
|
15
|
+
const KEYS: (keyof Inputs)[] = ["repositoryUrl", "repositoryDefaultBranch"];
|
|
26
16
|
|
|
27
|
-
/**
|
|
28
|
-
export interface Connected {
|
|
29
|
-
bitbucket: boolean;
|
|
30
|
-
jira: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const KEYS: (keyof Inputs)[] = ["repositoryUrl", "repositoryDefaultBranch", "jiraSite", "jiraEmail"];
|
|
34
|
-
|
|
35
|
-
/** What each token needs before it is used. */
|
|
36
|
-
const NEEDS: Record<keyof Connected, { inputs: (keyof Inputs)[]; variable: string; what: string }> = {
|
|
37
|
-
bitbucket: {
|
|
38
|
-
inputs: ["repositoryUrl", "repositoryDefaultBranch"],
|
|
39
|
-
variable: TOKEN_VARIABLES.bitbucket,
|
|
40
|
-
what: "repository",
|
|
41
|
-
},
|
|
42
|
-
jira: { inputs: ["jiraSite", "jiraEmail"], variable: TOKEN_VARIABLES.jira, what: "tracker" },
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const BARE_HOST = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/;
|
|
46
|
-
|
|
47
|
-
/** Reads inputs.json. An empty value stays empty; a value that is set but malformed stops synth. */
|
|
17
|
+
/** Reads inputs.json. A value that is missing or not a string reads as empty. */
|
|
48
18
|
export function readInputs(): Inputs {
|
|
49
19
|
const raw = JSON.parse(readFileSync(new URL("../inputs.json", import.meta.url), "utf8")) as Partial<Inputs>;
|
|
50
20
|
const inputs = {} as Inputs;
|
|
51
21
|
for (const key of KEYS) {
|
|
52
22
|
inputs[key] = typeof raw[key] === "string" ? raw[key].trim() : "";
|
|
53
23
|
}
|
|
54
|
-
if (
|
|
55
|
-
inputs.repositoryUrl !== "" &&
|
|
56
|
-
!/^https:\/\/bitbucket\.org\/[^/]+\/[^/]+$/.test(inputs.repositoryUrl.replace(/\.git$/, ""))
|
|
57
|
-
) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
`"repositoryUrl" in inputs.json must look like https://bitbucket.org/<workspace>/<repository>. ` +
|
|
60
|
-
`This template adds the token only for Bitbucket Cloud.`,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
if (inputs.jiraSite !== "" && !BARE_HOST.test(inputs.jiraSite)) {
|
|
64
|
-
throw new Error(`"jiraSite" in inputs.json must be a bare host such as acme.atlassian.net, with no https:// or path.`);
|
|
65
|
-
}
|
|
66
24
|
return inputs;
|
|
67
25
|
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Decides which tokens this apply adds, and declares one synth warning naming everything still missing.
|
|
71
|
-
* `orchestra fdk synth`, `diff` and `apply` print it and carry on.
|
|
72
|
-
*/
|
|
73
|
-
export function connect(factory: Factory, inputs: Inputs, env: NodeJS.ProcessEnv = process.env): Connected {
|
|
74
|
-
const connected = {} as Connected;
|
|
75
|
-
const missingInputs: string[] = [];
|
|
76
|
-
const missingVariables: string[] = [];
|
|
77
|
-
const notConnected: string[] = [];
|
|
78
|
-
for (const token of Object.keys(NEEDS) as (keyof Connected)[]) {
|
|
79
|
-
const need = NEEDS[token];
|
|
80
|
-
const inputsMissing = need.inputs.filter((key) => inputs[key] === "");
|
|
81
|
-
const variableMissing = (env[need.variable] ?? "").trim() === "";
|
|
82
|
-
connected[token] = inputsMissing.length === 0 && !variableMissing;
|
|
83
|
-
if (!connected[token]) {
|
|
84
|
-
notConnected.push(need.what);
|
|
85
|
-
missingInputs.push(...inputsMissing);
|
|
86
|
-
if (variableMissing) missingVariables.push(need.variable);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (notConnected.length > 0) {
|
|
90
|
-
const still = [
|
|
91
|
-
...(missingInputs.length > 0 ? [`${missingInputs.join(", ")} in inputs.json`] : []),
|
|
92
|
-
...(missingVariables.length > 0 ? [`${missingVariables.join(", ")} in the shell`] : []),
|
|
93
|
-
];
|
|
94
|
-
new Warning(
|
|
95
|
-
factory,
|
|
96
|
-
"not-connected",
|
|
97
|
-
`The ${notConnected.join(" and ")} ${notConnected.length > 1 ? "are" : "is"} not connected yet, so this ` +
|
|
98
|
-
`apply adds no token for ${notConnected.length > 1 ? "them" : "it"}. Still missing: ${still.join("; ")}. ` +
|
|
99
|
-
`Set them and apply again.`,
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
return connected;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** One plain warning in synth's output. It declares nothing on the platform. */
|
|
106
|
-
class Warning extends Construct {
|
|
107
|
-
readonly #message: string;
|
|
108
|
-
|
|
109
|
-
constructor(scope: Factory, id: string, message: string) {
|
|
110
|
-
super(scope, id);
|
|
111
|
-
this.#message = message;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
override _synthWarnings(): string[] {
|
|
115
|
-
return [this.#message];
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,48 +1,33 @@
|
|
|
1
|
-
// The whole factory, in the organization with no project: the
|
|
2
|
-
//
|
|
3
|
-
// creates it. It
|
|
1
|
+
// The whole factory, in the organization with no project: the four agents, their machines, the model gateway
|
|
2
|
+
// key, and the Bugs, Features and Support pipelines. `orchestra fdk diff` shows what this file declares, and
|
|
3
|
+
// `orchestra fdk apply` creates it. It declares no code host or tracker, so it applies with no token.
|
|
4
4
|
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import { Agent, Factory, Pipeline, type HarnessFamily } from "@orchestraworks/cli";
|
|
7
7
|
import { declareEnvironment, declareKeys, type Size } from "./lib/environment.js";
|
|
8
|
-
import {
|
|
8
|
+
import { readInputs, type Inputs } from "./lib/inputs.js";
|
|
9
9
|
|
|
10
10
|
const inputs = readInputs();
|
|
11
11
|
const factory = new Factory({ name: "factory" });
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
const keys = declareKeys(factory, inputs, connected);
|
|
13
|
+
const keys = declareKeys(factory);
|
|
15
14
|
|
|
16
15
|
function instructions(file: string): string {
|
|
17
16
|
return readFileSync(new URL(`./agents/${file}`, import.meta.url), "utf8")
|
|
18
|
-
.replace("<
|
|
17
|
+
.replace("<repository-notes>", repositoryNotes(inputs))
|
|
19
18
|
.replaceAll("<repository>", inputs.repositoryUrl)
|
|
20
|
-
.replaceAll("<branch>", inputs.repositoryDefaultBranch || "the default branch")
|
|
21
|
-
.replaceAll("<jira-site>", inputs.jiraSite);
|
|
19
|
+
.replaceAll("<branch>", inputs.repositoryDefaultBranch || "the default branch");
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
/** What the Manager Agent is told about the
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"The team's code is in <repository>. Pull requests go to <branch>.
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const lines = [
|
|
34
|
-
bitbucket
|
|
35
|
-
? "The team's code is in <repository>. Pull requests go to <branch>. The platform adds the Bitbucket token " +
|
|
36
|
-
"to your requests, so git and its API work without a password."
|
|
37
|
-
: "The team's repository is not connected yet.",
|
|
38
|
-
jira
|
|
39
|
-
? "Their issues are in Jira at <jira-site>. The platform adds the Jira token to your requests, so its API " +
|
|
40
|
-
"works without a password."
|
|
41
|
-
: "The team's tracker is not connected yet.",
|
|
42
|
-
"Until a person connects it, do not start an item that needs it: move the item to Needs review and ask for " +
|
|
43
|
-
"the connection.",
|
|
44
|
-
];
|
|
45
|
-
return lines.join("\n");
|
|
22
|
+
/** What the Manager Agent is told about where the code is, by what inputs.json names. */
|
|
23
|
+
function repositoryNotes({ repositoryUrl }: Inputs): string {
|
|
24
|
+
return [
|
|
25
|
+
repositoryUrl !== ""
|
|
26
|
+
? "The team's code is in <repository>. Pull requests go to <branch>."
|
|
27
|
+
: "This factory names no repository. Take the repository's address from the item.",
|
|
28
|
+
"No code host or tracker token is set up for you. A public repository clones without one. When you cannot",
|
|
29
|
+
"read the repository, move the item to its review stage and ask a person how to reach it.",
|
|
30
|
+
].join("\n");
|
|
46
31
|
}
|
|
47
32
|
|
|
48
33
|
const ENGINEERS: { size: Size; harness: HarnessFamily; model: string }[] = [
|
|
@@ -56,69 +41,37 @@ function reviewerOf(size: Size): string {
|
|
|
56
41
|
return size === "lg" ? "engineer-md" : "engineer-lg";
|
|
57
42
|
}
|
|
58
43
|
|
|
59
|
-
// The Manager Agent reaches Bitbucket and Jira with the team's tokens.
|
|
60
44
|
new Agent(factory, "manager-agent", {
|
|
61
45
|
slug: "manager-agent",
|
|
62
46
|
name: "Manager Agent",
|
|
63
|
-
environment: declareEnvironment(factory, "manager-work-lg", "lg", keys
|
|
47
|
+
environment: declareEnvironment(factory, "manager-work-lg", "lg", keys),
|
|
64
48
|
harness: "claude",
|
|
65
49
|
modelSettings: { model: "claude-opus-5-5", enableModelGateway: true },
|
|
66
50
|
instructions: instructions("manager-agent.md"),
|
|
67
51
|
});
|
|
68
52
|
|
|
69
53
|
for (const { size, harness, model } of ENGINEERS) {
|
|
70
|
-
// Blocked from Bitbucket and Jira until commissioning: the code arrives as a git bundle instead.
|
|
71
|
-
const environment = declareEnvironment(factory, `engineer-work-${size}`, size, keys, inputs, {
|
|
72
|
-
access: "blocked",
|
|
73
|
-
codex: harness === "codex",
|
|
74
|
-
});
|
|
75
54
|
new Agent(factory, `engineer-${size}`, {
|
|
76
55
|
slug: `engineer-${size}`,
|
|
77
56
|
name: `Engineer Agent ${size}`,
|
|
78
|
-
environment,
|
|
57
|
+
environment: declareEnvironment(factory, `engineer-work-${size}`, size, keys, {
|
|
58
|
+
codex: harness === "codex",
|
|
59
|
+
}),
|
|
79
60
|
harness,
|
|
80
61
|
modelSettings: { model, enableModelGateway: true },
|
|
81
62
|
instructions: instructions("engineer-agent.md")
|
|
63
|
+
.replaceAll("<self-name>", `Engineer Agent ${size}`)
|
|
82
64
|
.replaceAll("<self>", `engineer-${size}`)
|
|
83
65
|
.replaceAll("<reviewer>", reviewerOf(size)),
|
|
84
66
|
});
|
|
85
|
-
if (size === "lg") {
|
|
86
|
-
// The Bootstrap's baseline, on engineer-lg's machine shape and model, with no codebase skill and no work
|
|
87
|
-
// loop, so its replays measure what the study and the loop add. Never give it a skill.
|
|
88
|
-
new Agent(factory, "engineer-bare", {
|
|
89
|
-
slug: "engineer-bare",
|
|
90
|
-
name: "Engineer Agent bare",
|
|
91
|
-
environment,
|
|
92
|
-
harness,
|
|
93
|
-
modelSettings: { model, enableModelGateway: true },
|
|
94
|
-
instructions: instructions("engineer-bare.md"),
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
67
|
}
|
|
98
68
|
|
|
99
69
|
// No stage limits where an item may move next: a person or an agent moves it wherever the work stands.
|
|
100
|
-
|
|
101
|
-
// Set up, Bootstrap and every Replay item live here, until commissioning.
|
|
102
|
-
new Pipeline(factory, "onboarding", {
|
|
103
|
-
slug: "onboarding",
|
|
104
|
-
name: "Onboarding",
|
|
105
|
-
description:
|
|
106
|
-
"The steps to a working factory: connect the code and the tracker, make the repository run on our machines, learn how this team works, and prove the agents on past fixes before they take real work. Each step is an item here. This pipeline is retired after commissioning.",
|
|
107
|
-
itemSlugPrefix: "onbd",
|
|
108
|
-
stages: [
|
|
109
|
-
{ slug: "todo", name: "Todo", category: "TODO" },
|
|
110
|
-
{ slug: "in-progress", name: "In progress", category: "IN_PROGRESS" },
|
|
111
|
-
{ slug: "needs-review", name: "Needs review", category: "IN_PROGRESS" },
|
|
112
|
-
{ slug: "done", name: "Done", category: "DONE" },
|
|
113
|
-
],
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// The pipelines real work flows through.
|
|
117
70
|
new Pipeline(factory, "bugs", {
|
|
118
71
|
slug: "bugs",
|
|
119
72
|
name: "Bugs",
|
|
120
73
|
description:
|
|
121
|
-
"Bugs the Engineer Agents fix. New issues land in Triage. Parked holds a bug
|
|
74
|
+
"Bugs the Engineer Agents fix. New issues land in Triage. Parked holds a bug a person has set aside. A fix waits in In review as a pull request with a test that failed before and passes after.",
|
|
122
75
|
itemSlugPrefix: "bug",
|
|
123
76
|
stages: [
|
|
124
77
|
{ slug: "triage", name: "Triage", category: "TODO" },
|
|
@@ -6,5 +6,5 @@ You fix bugs in the GitHub repository <repository>, one bug per conversation. Th
|
|
|
6
6
|
3. Fix it with the smallest change and run the test again. Keep the passing output.
|
|
7
7
|
4. Push a branch as soon as the test passes, then open a pull request against the default branch with gh:
|
|
8
8
|
what was wrong, the fix, and the tests you ran.
|
|
9
|
-
5. Publish a report with your
|
|
9
|
+
5. Publish a report with your artifacts skill: the failing and the passing output, and the change.
|
|
10
10
|
End with the pull request's link and the report's slug.
|
|
@@ -106,7 +106,7 @@ new Agent(factory, "bugfix", {
|
|
|
106
106
|
modelSettings: { enableModelGateway: true },
|
|
107
107
|
instructions: readFile("agents/bugfix.md").replaceAll("<repository>", REPOSITORY),
|
|
108
108
|
skills: [
|
|
109
|
-
Skill.fromId(factory, "
|
|
109
|
+
Skill.fromId(factory, "skill_artifacts"),
|
|
110
110
|
new Skill(factory, "codebase", { source: "skills/codebase" }),
|
|
111
111
|
],
|
|
112
112
|
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
You are Engineer Agent engineer-bare. You make the change one item asks for, in this team's code, one item
|
|
2
|
-
per conversation. The item is your first message.
|
|
3
|
-
|
|
4
|
-
You cannot reach Bitbucket or Jira from this machine. The code comes as a git bundle, a file the Manager
|
|
5
|
-
Agent uploaded. Its id is on the item's `Code bundle:` line.
|
|
6
|
-
|
|
7
|
-
1. Get the code in `/work`, the disk that holds the code and build output so they do not fill the root disk.
|
|
8
|
-
Run `cd /work`, then `orchestra files get-content <file id> --output-file work.bundle`, then
|
|
9
|
-
`git clone --branch work work.bundle code`, and work in `/work/code`.
|
|
10
|
-
2. Make the change the item asks for.
|
|
11
|
-
3. Write your whole change as one patch, new files and any commits included, against the commit the bundle
|
|
12
|
-
holds: `git -C /work/code add -A`, then
|
|
13
|
-
`git -C /work/code diff --cached --binary origin/work > /work/change.patch`. Upload it with
|
|
14
|
-
`orchestra files create --file /work/change.patch --filename change.patch --output json`.
|
|
15
|
-
4. Add a comment to the item with `orchestra work-items create-activity <item id> --text <comment>` that gives the
|
|
16
|
-
patch's File id. Move the item to Needs review and assign it to `manager-agent`. Assigning it starts the
|
|
17
|
-
Manager Agent's conversation, which scores your change.
|
|
18
|
-
|
|
19
|
-
Do not try to find the issue's real fix anywhere else. When you are stuck, say what you need in the comment,
|
|
20
|
-
move the item to Needs review and assign it to `manager-agent`.
|
|
21
|
-
|
|
22
|
-
Stop any Monitor or background task you started before your final message.
|